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 implementationconfig.go- Configuration and trust policyresolver.go- DID and PDS resolutioncrypto.go- K-256 signature verificationDockerfile- Build custom Ratify image with plugindeployment.yaml- Kubernetes deployment manifestverifier-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#
# 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#
# Push custom image
docker push atcr.io/atcr/ratify-with-atproto:latest
# Deploy Ratify
kubectl apply -f deployment.yaml
2. Configure Verifier#
# Create Verifier custom resource
kubectl apply -f verifier-crd.yaml
3. Configure Trust Policy#
# Create ConfigMap with trust policy
kubectl create configmap atcr-trust-policy \
--from-file=trust-policy.yaml \
-n gatekeeper-system
4. Create Gatekeeper Constraint#
kubectl apply -f constraint.yaml
5. Test#
# 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#
# 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#
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:
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#
- Artifact Fetch: Download signature artifact from registry via Ratify's store
- Parse Metadata: Extract ATProto signature metadata (DID, PDS, commit CID)
- DID Resolution: Resolve DID to public key via PLC directory or did:web
- Commit Fetch: Get repository commit from PDS via XRPC
- Signature Verify: Verify ECDSA K-256 signature over commit bytes
- Trust Check: Validate DID against trust policy
- Result: Return success/failure with metadata
Error Handling#
The plugin returns detailed error information:
type VerifierResult struct {
IsSuccess bool
Name string
Type string
Message string
Extensions map[string]interface{}
}
Extensions include:
did- Signer's DIDhandle- Signer's handle (if available)signedAt- Signature timestampcommitCid- ATProto commit CIDpdsEndpoint- PDS URLerror- Error details (if verification failed)
Troubleshooting#
Plugin Not Found#
# 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#
# 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#
# 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#
Support#
For issues or questions:
- GitHub Issues: https://github.com/atcr-io/atcr/issues
- Ratify GitHub: https://github.com/ratify-project/ratify