ATProto Signature Verification Plugins and Examples#
This directory contains reference implementations and examples for integrating ATProto signature verification into various tools and workflows.
Overview#
ATCR uses ATProto's native signature system to cryptographically sign container images. To integrate signature verification into existing tools (Kubernetes, CI/CD, container runtimes), you can:
- Build plugins for verification frameworks (Ratify, Gatekeeper, Containerd)
- Use external services called by policy engines
- Integrate CLI tools in your CI/CD pipelines
Directory Structure#
examples/plugins/
├── README.md # This file
├── ratify-verifier/ # Ratify plugin for Kubernetes
│ ├── README.md
│ ├── verifier.go
│ ├── config.go
│ ├── resolver.go
│ ├── crypto.go
│ ├── Dockerfile
│ ├── deployment.yaml
│ └── verifier-crd.yaml
├── gatekeeper-provider/ # OPA Gatekeeper external provider
│ ├── README.md
│ ├── main.go
│ ├── verifier.go
│ ├── resolver.go
│ ├── crypto.go
│ ├── Dockerfile
│ ├── deployment.yaml
│ └── provider-crd.yaml
├── containerd-verifier/ # Containerd bindir plugin
│ ├── README.md
│ ├── main.go
│ └── Dockerfile
└── ci-cd/ # CI/CD integration examples
├── github-actions.yml
├── gitlab-ci.yml
└── jenkins-pipeline.groovy
Quick Start#
For Kubernetes (Recommended)#
Option A: Ratify Plugin
cd ratify-verifier
# Build plugin and deploy to Kubernetes
./build.sh
kubectl apply -f deployment.yaml
kubectl apply -f verifier-crd.yaml
Option B: Gatekeeper Provider
cd gatekeeper-provider
# Build and deploy external provider
docker build -t atcr.io/atcr/gatekeeper-provider:latest .
kubectl apply -f deployment.yaml
kubectl apply -f provider-crd.yaml
For CI/CD#
GitHub Actions
# Copy examples/plugins/ci-cd/github-actions.yml to .github/workflows/
cp ci-cd/github-actions.yml ../.github/workflows/verify-and-deploy.yml
GitLab CI
# Copy examples/plugins/ci-cd/gitlab-ci.yml to your repo
cp ci-cd/gitlab-ci.yml ../.gitlab-ci.yml
For Containerd#
cd containerd-verifier
# Build plugin
./build.sh
# Install to containerd plugins directory
sudo cp atcr-verifier /opt/containerd/bin/
Plugins Overview#
Ratify Verifier Plugin ⭐#
Use case: Kubernetes admission control with OPA Gatekeeper
How it works:
- Gatekeeper receives pod creation request
- Calls Ratify verification engine
- Ratify loads ATProto verifier plugin
- Plugin verifies signature and checks trust policy
- Returns allow/deny decision to Gatekeeper
Pros:
- Standard Ratify plugin interface
- Works with existing Gatekeeper deployments
- Can combine with other verifiers (Notation, Cosign)
- Policy-based enforcement
Cons:
- Requires building custom Ratify image
- Plugin must be compiled into image
- More complex deployment
See: ratify-verifier/README.md
Gatekeeper External Provider ⭐#
Use case: Kubernetes admission control with OPA Gatekeeper
How it works:
- Gatekeeper receives pod creation request
- Rego policy calls external data provider API
- Provider verifies ATProto signature
- Returns verification result to Gatekeeper
- Rego policy makes allow/deny decision
Pros:
- Simpler deployment (separate service)
- Easy to update (no Gatekeeper changes)
- Flexible Rego policies
- Can add caching, rate limiting
Cons:
- Additional service to maintain
- Network dependency (provider must be reachable)
- Slightly higher latency
See: gatekeeper-provider/README.md
Containerd Bindir Plugin#
Use case: Runtime-level verification for all images
How it works:
- Containerd pulls image
- Calls verifier plugin (bindir)
- Plugin verifies ATProto signature
- Returns result to containerd
- Containerd allows/blocks image
Pros:
- Works at runtime level (not just Kubernetes)
- CRI-O, Podman support (CRI-compatible)
- No Kubernetes required
- Applies to all images
Cons:
- Containerd 2.0+ required
- More complex to debug
- Less flexible policies
See: containerd-verifier/README.md
CI/CD Integration Examples#
GitHub Actions#
Complete workflow with:
- Image signature verification
- DID trust checking
- Automated deployment on success
GitLab CI#
Pipeline with:
- Multi-stage verification
- Trust policy enforcement
- Manual deployment approval
See: ci-cd/gitlab-ci.yml
Jenkins#
Declarative pipeline with:
- Signature verification stage
- Deployment gates
- Rollback on failure
See: ci-cd/jenkins-pipeline.groovy (coming soon)
Common Components#
All plugins share common functionality:
DID Resolution#
Resolve DID to public key:
func ResolveDIDToPublicKey(ctx context.Context, did string) (*PublicKey, error)
Steps:
- Fetch DID document from PLC directory or did:web
- Extract verification method
- Decode multibase public key
- Parse as K-256 public key
PDS Communication#
Fetch repository commit:
func FetchCommit(ctx context.Context, pdsEndpoint, did, commitCID string) (*Commit, error)
Steps:
- Call
com.atproto.sync.getRepoXRPC endpoint - Parse CAR file response
- Extract commit with matching CID
- Return commit data and signature
Signature Verification#
Verify ECDSA K-256 signature:
func VerifySignature(pubKey *PublicKey, commit *Commit) error
Steps:
- Extract unsigned commit bytes
- Hash with SHA-256
- Verify ECDSA signature over hash
- Check signature is valid for public key
Trust Policy#
Check if DID is trusted:
func IsTrusted(did string, now time.Time) bool
Steps:
- Load trust policy from config
- Check if DID in trusted list
- Verify validFrom/expiresAt timestamps
- Return true if trusted
Trust Policy Format#
All plugins use the same trust policy format:
version: 1.0
trustedDIDs:
did:plc:alice123:
name: "Alice (DevOps Lead)"
validFrom: "2024-01-01T00:00:00Z"
expiresAt: null
did:plc:bob456:
name: "Bob (Security Team)"
validFrom: "2024-06-01T00:00:00Z"
expiresAt: "2025-12-31T23:59:59Z"
policies:
- name: production-images
scope: "atcr.io/*/prod-*"
require:
signature: true
trustedDIDs:
- did:plc:alice123
- did:plc:bob456
minSignatures: 1
action: enforce
- name: dev-images
scope: "atcr.io/*/dev-*"
require:
signature: false
action: audit
Implementation Notes#
Dependencies#
All plugins require:
- Go 1.21+ for building
- ATProto DID resolution (PLC directory, did:web)
- ATProto PDS XRPC API access
- ECDSA K-256 signature verification
Caching#
Recommended caching strategy:
- DID documents: 5 minute TTL
- Public keys: 5 minute TTL
- PDS endpoints: 5 minute TTL
- Signature results: 5 minute TTL
Error Handling#
Plugins should handle:
- DID resolution failures (network, invalid DID)
- PDS connectivity issues (timeout, 404, 500)
- Invalid signature format
- Untrusted DIDs
- Network timeouts
Logging#
Structured logging with:
image- Image being verifieddid- Signer DIDduration- Operation durationerror- Error message (if failed)
Metrics#
Expose Prometheus metrics:
atcr_verifications_total{result="verified|failed|error"}atcr_verification_duration_secondsatcr_did_resolutions_total{result="success|failure"}atcr_cache_hits_totalatcr_cache_misses_total
Testing#
Unit Tests#
Test individual components:
# Test DID resolution
go test ./pkg/resolver -v
# Test signature verification
go test ./pkg/crypto -v
# Test trust policy
go test ./pkg/trust -v
Integration Tests#
Test with real services:
# Test against ATCR registry
go test ./integration -tags=integration -v
# Test with test PDS
go test ./integration -tags=integration -pds=https://test.pds.example.com
End-to-End Tests#
Test full deployment:
# Deploy to test cluster
kubectl apply -f test/fixtures/
# Create pod with signed image (should succeed)
kubectl run test-signed --image=atcr.io/test/signed:latest
# Create pod with unsigned image (should fail)
kubectl run test-unsigned --image=atcr.io/test/unsigned:latest
Performance Considerations#
Latency#
Typical verification latency:
- DID resolution: 50-200ms (cached: <1ms)
- PDS query: 100-500ms (cached: <1ms)
- Signature verification: 1-5ms
- Total: 150-700ms (uncached), <10ms (cached)
Throughput#
Expected throughput (single instance):
- Without caching: ~5-10 verifications/second
- With caching: ~100-500 verifications/second
Scaling#
For high traffic:
- Deploy multiple replicas (stateless)
- Use Redis for distributed caching
- Implement rate limiting
- Monitor P95/P99 latency
Security Considerations#
Network Policies#
Restrict access to:
- DID resolution (PLC directory only)
- PDS XRPC endpoints
- Internal services only
Denial of Service#
Protect against:
- High verification request rate
- Slow DID resolution
- Malicious images with many signatures
- Large signature artifacts
Trust Model#
Understand trust dependencies:
- DID resolution is accurate (PLC directory)
- PDS serves correct records
- Private keys are secure
- Trust policy is maintained
Troubleshooting#
Plugin Not Loading#
# Check plugin exists
ls -la /path/to/plugin
# Check plugin is executable
chmod +x /path/to/plugin
# Check plugin logs
tail -f /var/log/atcr-verifier.log
Verification Failing#
# Test DID resolution
curl https://plc.directory/did:plc:alice123
# Test PDS connectivity
curl https://bsky.social/xrpc/com.atproto.server.describeServer
# Test signature exists
oras discover atcr.io/alice/myapp:latest \
--artifact-type application/vnd.atproto.signature.v1+json
Policy Not Enforcing#
# Check policy is loaded
kubectl get configmap atcr-trust-policy -n gatekeeper-system
# Check constraint is active
kubectl get constraint atcr-signatures-required -o yaml
# Check logs
kubectl logs -n gatekeeper-system deployment/ratify
See Also#
Documentation#
- ATProto Signatures - Technical deep-dive
- Signature Integration - Tool-specific guides
- Integration Strategy - High-level overview
- atcr-verify CLI - CLI tool specification
Examples#
- Verification Scripts - Shell scripts for manual verification
- Kubernetes Webhook - Custom webhook example
External Resources#
- Ratify - Verification framework
- OPA Gatekeeper - Policy engine
- Containerd - Container runtime
Support#
For questions or issues:
- GitHub Issues: https://github.com/atcr-io/atcr/issues
- Documentation: https://docs.atcr.io
- Security: security@atcr.io
Contributing#
Contributions welcome! Please:
- Follow existing code structure
- Add tests for new features
- Update documentation
- Submit pull request
License#
See LICENSE file in repository root.