# Ratify ATProto Verifier Plugin This is a reference implementation of a Ratify verifier plugin for ATProto signatures. ## Overview Ratify is a verification framework that integrates with OPA Gatekeeper to enforce signature policies in Kubernetes. This plugin adds support for verifying ATProto signatures on ATCR container images. ## Architecture ``` Kubernetes Pod Creation ↓ OPA Gatekeeper (admission webhook) ↓ Ratify (verification engine) ↓ ATProto Verifier Plugin ← This plugin ↓ 1. Fetch signature artifact from registry 2. Parse ATProto signature metadata 3. Resolve DID to public key 4. Fetch repository commit from PDS 5. Verify ECDSA K-256 signature 6. Check trust policy ↓ Return: Allow/Deny ``` ## Files - `verifier.go` - Main verifier implementation - `config.go` - Configuration and trust policy - `resolver.go` - DID and PDS resolution - `crypto.go` - K-256 signature verification - `Dockerfile` - Build custom Ratify image with plugin - `deployment.yaml` - Kubernetes deployment manifest - `verifier-crd.yaml` - Ratify Verifier custom resource ## Prerequisites - Go 1.21+ - Ratify source code (for building plugin) - Kubernetes cluster with OPA Gatekeeper installed - Access to ATCR registry ## Building ```bash # Clone Ratify git clone https://github.com/ratify-project/ratify.git cd ratify # Copy plugin files cp -r /path/to/examples/plugins/ratify-verifier plugins/verifier/atproto/ # Build plugin CGO_ENABLED=0 go build -o atproto-verifier \ -ldflags="-w -s" \ ./plugins/verifier/atproto # Build custom Ratify image with plugin docker build -f Dockerfile.with-atproto -t atcr.io/atcr/ratify-with-atproto:latest . ``` ## Deployment ### 1. Deploy Ratify with Plugin ```bash # Push custom image docker push atcr.io/atcr/ratify-with-atproto:latest # Deploy Ratify kubectl apply -f deployment.yaml ``` ### 2. Configure Verifier ```bash # Create Verifier custom resource kubectl apply -f verifier-crd.yaml ``` ### 3. Configure Trust Policy ```bash # Create ConfigMap with trust policy kubectl create configmap atcr-trust-policy \ --from-file=trust-policy.yaml \ -n gatekeeper-system ``` ### 4. Create Gatekeeper Constraint ```bash kubectl apply -f constraint.yaml ``` ### 5. Test ```bash # Try to create pod with signed image (should succeed) kubectl run test-signed --image=atcr.io/alice/myapp:latest # Try to create pod with unsigned image (should fail) kubectl run test-unsigned --image=atcr.io/malicious/fake:latest ``` ## Configuration ### Trust Policy Format ```yaml # trust-policy.yaml version: 1.0 trustedDIDs: did:plc:alice123: name: "Alice (DevOps)" validFrom: "2024-01-01T00:00:00Z" expiresAt: null did:plc:bob456: name: "Bob (Security)" validFrom: "2024-06-01T00:00:00Z" expiresAt: "2025-12-31T23:59:59Z" policies: - name: production scope: "atcr.io/*/prod-*" require: signature: true trustedDIDs: - did:plc:alice123 - did:plc:bob456 action: enforce ``` ### Verifier Configuration ```yaml apiVersion: config.ratify.deislabs.io/v1beta1 kind: Verifier metadata: name: atproto-verifier spec: name: atproto artifactType: application/vnd.atproto.signature.v1+json address: /.ratify/plugins/atproto-verifier parameters: trustPolicyPath: /config/trust-policy.yaml didResolverTimeout: 10s pdsTimeout: 10s cacheEnabled: true cacheTTL: 300s ``` ## Implementation Details ### Verifier Interface The plugin implements Ratify's `ReferenceVerifier` interface: ```go type ReferenceVerifier interface { Name() string Type() string CanVerify(artifactType string) bool VerifyReference( ctx context.Context, subjectRef common.Reference, referenceDesc ocispecs.ReferenceDescriptor, store referrerstore.ReferrerStore, ) (VerifierResult, error) } ``` ### Verification Flow 1. **Artifact Fetch**: Download signature artifact from registry via Ratify's store 2. **Parse Metadata**: Extract ATProto signature metadata (DID, PDS, commit CID) 3. **DID Resolution**: Resolve DID to public key via PLC directory or did:web 4. **Commit Fetch**: Get repository commit from PDS via XRPC 5. **Signature Verify**: Verify ECDSA K-256 signature over commit bytes 6. **Trust Check**: Validate DID against trust policy 7. **Result**: Return success/failure with metadata ### Error Handling The plugin returns detailed error information: ```go type VerifierResult struct { IsSuccess bool Name string Type string Message string Extensions map[string]interface{} } ``` **Extensions include:** - `did` - Signer's DID - `handle` - Signer's handle (if available) - `signedAt` - Signature timestamp - `commitCid` - ATProto commit CID - `pdsEndpoint` - PDS URL - `error` - Error details (if verification failed) ## Troubleshooting ### Plugin Not Found ```bash # Check plugin is in image kubectl exec -n gatekeeper-system deployment/ratify -c ratify -- ls -la /.ratify/plugins/ # Check logs kubectl logs -n gatekeeper-system deployment/ratify -c ratify ``` ### Verification Failing ```bash # Check Ratify logs for details kubectl logs -n gatekeeper-system deployment/ratify -c ratify | grep atproto # Check Verifier status kubectl get verifier atproto-verifier -o yaml # Test DID resolution manually curl https://plc.directory/did:plc:alice123 ``` ### Trust Policy Issues ```bash # Check ConfigMap exists kubectl get configmap atcr-trust-policy -n gatekeeper-system # View policy contents kubectl get configmap atcr-trust-policy -n gatekeeper-system -o yaml ``` ## Performance Considerations ### Caching The plugin caches: - DID documents (TTL: 5 minutes) - PDS endpoints (TTL: 5 minutes) - Public keys (TTL: 5 minutes) Configure via `cacheEnabled` and `cacheTTL` parameters. ### Timeouts Configure timeouts for external calls: - `didResolverTimeout` - DID resolution (default: 10s) - `pdsTimeout` - PDS XRPC calls (default: 10s) ### Rate Limiting Consider implementing rate limiting for: - DID resolution (PLC directory) - PDS XRPC calls - Signature verification ## Security Considerations ### Trust Policy Management - Store trust policy in version control - Review DID additions/removals carefully - Set expiration dates for temporary access - Audit trust policy changes ### Private Key Protection - Plugin only uses public keys - No private keys needed for verification - DID resolution is read-only - PDS queries are read-only ### Denial of Service - Implement timeouts for all external calls - Cache DID documents to reduce load - Rate limit verification requests - Monitor verification latency ## See Also - [Ratify Documentation](https://ratify.dev/) - [Ratify Plugin Development](https://ratify.dev/docs/plugins/verifier/overview) - [ATCR Signature Integration](../../../docs/SIGNATURE_INTEGRATION.md) - [ATCR Integration Strategy](../../../docs/INTEGRATION_STRATEGY.md) ## Support For issues or questions: - GitHub Issues: https://github.com/atcr-io/atcr/issues - Ratify GitHub: https://github.com/ratify-project/ratify