# 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 ```bash # 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 ```bash # 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:** ```bash # 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 ```bash # 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):** ```bash brew install curl jq crane oras ``` **Linux (apt):** ```bash # 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:** ```bash # 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:** ```yaml trustedDIDs: did:plc:your-did: name: "Your Name" validFrom: "2024-01-01T00:00:00Z" ``` 2. **Define policies:** ```yaml policies: - name: my-policy scope: "atcr.io/myorg/*" require: signature: true trustedDIDs: - did:plc:your-did action: enforce ``` 3. **Use with verification:** ```bash # When atcr-verify CLI is available: atcr-verify IMAGE --policy trust-policy.yaml ``` ## Integration Patterns ### CI/CD (GitHub Actions) ```yaml - 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) ```yaml 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 ```bash # ~/.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 ```ini # /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: ```bash 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 - [ATProto Signatures](../../docs/ATPROTO_SIGNATURES.md) - Technical details - [Signature Integration](../../docs/SIGNATURE_INTEGRATION.md) - Integration guide - [SBOM Scanning](../../docs/SBOM_SCANNING.md) - Similar ORAS pattern ## Support For issues or questions: - GitHub Issues: https://github.com/your-org/atcr/issues - Documentation: https://docs.atcr.io - Security: security@yourorg.com