12 KiB
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.