Files
2025-10-31 21:03:33 -05:00

9.9 KiB

ATProto Signature Verification Examples

This directory contains practical examples for verifying ATProto signatures on ATCR container images.

Files

Scripts

  • atcr-verify.sh - Standalone signature verification script

    • Verifies ATProto signatures using shell commands
    • Requires: curl, jq, crane, oras
    • Does everything except full cryptographic verification
    • Use this until the atcr-verify CLI tool is built
  • verify-and-pull.sh - Secure image pull wrapper

    • Verifies signatures before pulling images
    • Can be used as a docker pull replacement
    • Configurable via environment variables

Configuration

  • trust-policy.yaml - Example trust policy configuration

    • Defines which DIDs to trust
    • Specifies policies for different image scopes
    • Includes audit logging and reporting settings
  • kubernetes-webhook.yaml - Kubernetes admission controller

    • Validates signatures before pod creation
    • Includes webhook deployment, service, and configuration
    • Uses trust policy ConfigMap

Quick Start

1. Verify an Image

# Make script executable
chmod +x atcr-verify.sh

# Verify an image
./atcr-verify.sh atcr.io/alice/myapp:latest

Output:

═══════════════════════════════════════════════════
 ATProto Signature Verification
═══════════════════════════════════════════════════
 Image: atcr.io/alice/myapp:latest
═══════════════════════════════════════════════════

[1/7] Resolving image digest...
  → sha256:abc123...
[2/7] Discovering ATProto signature artifacts...
  → Found 1 signature(s)
  → Signature digest: sha256:sig789...
  → Signed by DID: did:plc:alice123
[3/7] Fetching signature metadata...
  → DID: did:plc:alice123
  → Handle: alice.bsky.social
  → PDS: https://bsky.social
  → Record: at://did:plc:alice123/io.atcr.manifest/abc123
  → Signed at: 2025-10-31T12:34:56.789Z
[4/7] Resolving DID to public key...
  → Public key: zQ3shokFTS3brHcD...
[5/7] Querying PDS for signed record...
  → Record CID: bafyreig7...
[6/7] Verifying record integrity...
  → Record digest matches image digest
[7/7] Cryptographic signature verification...
  ⚠ Full cryptographic verification requires ATProto crypto library

═══════════════════════════════════════════════════
 ✓ Verification Completed
═══════════════════════════════════════════════════

 Signed by:    alice.bsky.social (did:plc:alice123)
 Signed at:    2025-10-31T12:34:56.789Z
 PDS:          https://bsky.social
 Record:       at://did:plc:alice123/io.atcr.manifest/abc123
 Signature:    sha256:sig789...

═══════════════════════════════════════════════════

2. Secure Pull

# Make script executable
chmod +x verify-and-pull.sh

# Pull image with verification
./verify-and-pull.sh atcr.io/alice/myapp:latest

# With Docker options
./verify-and-pull.sh atcr.io/alice/myapp:latest --platform linux/amd64

Create an alias for convenience:

# Add to ~/.bashrc or ~/.zshrc
alias docker-pull-secure='/path/to/verify-and-pull.sh'

# Use it
docker-pull-secure atcr.io/alice/myapp:latest

3. Deploy Kubernetes Webhook

# 1. Generate TLS certificates for webhook
openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt \
  -days 365 -nodes -subj "/CN=atcr-verify-webhook.atcr-system.svc"

# 2. Create namespace and secret
kubectl create namespace atcr-system
kubectl create secret tls atcr-verify-webhook-certs \
  --cert=tls.crt --key=tls.key -n atcr-system

# 3. Update CA bundle in kubernetes-webhook.yaml
cat tls.crt | base64 -w 0
# Copy output and replace caBundle in kubernetes-webhook.yaml

# 4. Deploy webhook
kubectl apply -f kubernetes-webhook.yaml

# 5. Enable verification for a namespace
kubectl label namespace production atcr-verify=enabled

# 6. Test with a pod
kubectl run test-pod --image=atcr.io/alice/myapp:latest -n production

Prerequisites

For Scripts

Install required tools:

macOS (Homebrew):

brew install curl jq crane oras

Linux (apt):

# curl and jq
sudo apt-get install curl jq

# crane
curl -sL "https://github.com/google/go-containerregistry/releases/download/v0.15.2/go-containerregistry_Linux_x86_64.tar.gz" | tar -xz crane
sudo mv crane /usr/local/bin/

# oras
curl -LO "https://github.com/oras-project/oras/releases/download/v1.0.0/oras_1.0.0_linux_amd64.tar.gz"
tar -xzf oras_1.0.0_linux_amd64.tar.gz
sudo mv oras /usr/local/bin/

For Kubernetes Webhook

Requirements:

  • Kubernetes cluster (1.16+)
  • kubectl configured
  • Permission to create namespaces and webhooks
  • Webhook container image (build from source or use pre-built)

Configuration

Environment Variables (verify-and-pull.sh)

  • VERIFY_SCRIPT - Path to atcr-verify.sh (default: ./atcr-verify.sh)
  • TRUST_POLICY - Path to trust policy (default: ./trust-policy.yaml)
  • REQUIRE_VERIFICATION - Require verification (default: true)
  • SKIP_ATCR_IMAGES - Skip verification for non-ATCR images (default: false)

Example:

# Skip verification for non-ATCR images
SKIP_ATCR_IMAGES=true ./verify-and-pull.sh docker.io/library/nginx:latest

# Allow pulling even if verification fails (NOT RECOMMENDED)
REQUIRE_VERIFICATION=false ./verify-and-pull.sh atcr.io/alice/myapp:latest

Trust Policy

Edit trust-policy.yaml to customize:

  1. Add your DIDs:

    trustedDIDs:
      did:plc:your-did:
        name: "Your Name"
        validFrom: "2024-01-01T00:00:00Z"
    
  2. Define policies:

    policies:
      - name: my-policy
        scope: "atcr.io/myorg/*"
        require:
          signature: true
          trustedDIDs:
            - did:plc:your-did
        action: enforce
    
  3. Use with verification:

    # When atcr-verify CLI is available:
    atcr-verify IMAGE --policy trust-policy.yaml
    

Integration Patterns

CI/CD (GitHub Actions)

- name: Verify image signature
  run: |
    chmod +x examples/verification/atcr-verify.sh
    ./examples/verification/atcr-verify.sh ${{ env.IMAGE }}

- name: Deploy if verified
  if: success()
  run: kubectl set image deployment/app app=${{ env.IMAGE }}

CI/CD (GitLab CI)

verify:
  script:
    - chmod +x examples/verification/atcr-verify.sh
    - ./examples/verification/atcr-verify.sh $IMAGE

deploy:
  dependencies: [verify]
  script:
    - kubectl set image deployment/app app=$IMAGE

Docker Alias

# ~/.bashrc or ~/.zshrc
function docker() {
  if [ "$1" = "pull" ] && [[ "$2" =~ ^atcr\.io/ ]]; then
    echo "Using secure pull with signature verification..."
    /path/to/verify-and-pull.sh "${@:2}"
  else
    command docker "$@"
  fi
}

Systemd Service

# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=docker.service

[Service]
Type=oneshot
ExecStartPre=/path/to/verify-and-pull.sh atcr.io/myorg/myapp:latest
ExecStart=/usr/bin/docker run atcr.io/myorg/myapp:latest
Restart=on-failure

[Install]
WantedBy=multi-user.target

Troubleshooting

"No ATProto signature found"

Cause: Image doesn't have a signature artifact

Solutions:

  1. Check if image exists: crane digest IMAGE
  2. Re-push image to generate signature
  3. Verify referrers API is working:
    curl "https://atcr.io/v2/REPO/referrers/DIGEST"
    

"Failed to resolve DID"

Cause: DID resolution failed

Solutions:

  1. Check internet connectivity
  2. Verify DID is valid: curl https://plc.directory/DID
  3. Check if DID document has verificationMethod

"Failed to fetch record from PDS"

Cause: PDS is unreachable or record doesn't exist

Solutions:

  1. Check PDS endpoint: curl PDS_URL/xrpc/com.atproto.server.describeServer
  2. Verify record URI is correct
  3. Check if record exists in PDS

Webhook Pods Don't Start

Cause: Webhook is rejecting all pods

Solutions:

  1. Check webhook logs: kubectl logs -n atcr-system -l app=atcr-verify-webhook
  2. Disable webhook temporarily: kubectl delete validatingwebhookconfiguration atcr-verify
  3. Fix issue and re-deploy
  4. Test with labeled namespace first

Security Best Practices

  1. Always verify in production

    • Enable webhook for production namespaces
    • Set failurePolicy: Fail to block on errors
  2. Use trust policies

    • Define specific trusted DIDs
    • Don't trust all signatures blindly
    • Set expiration dates for temporary access
  3. Monitor verification

    • Enable audit logging
    • Review verification failures
    • Track signature coverage
  4. Rotate keys regularly

    • Update DID documents when keys change
    • Revoke compromised keys immediately
    • Monitor for unexpected key changes
  5. Secure webhook deployment

    • Use TLS for webhook communication
    • Restrict webhook RBAC permissions
    • Keep webhook image updated

Next Steps

  1. Test verification with your images
  2. Customize trust policy for your organization
  3. Deploy webhook to test clusters first
  4. Monitor verification in CI/CD pipelines
  5. Gradually roll out to production

See Also

Support

For issues or questions: