A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
atcr.io
docker
container
atproto
go
1# ATCR Signature Verification Integration Strategy
2
3## Overview
4
5This document provides a comprehensive overview of how to integrate ATProto signature verification into various tools and workflows. ATCR uses a layered approach that provides maximum compatibility while maintaining ATProto's decentralized philosophy.
6
7## Architecture Layers
8
9```
10┌─────────────────────────────────────────────────────────┐
11│ Layer 4: Applications & Workflows │
12│ - CI/CD pipelines │
13│ - Kubernetes admission control │
14│ - Runtime verification │
15│ - Security scanning │
16└──────────────────────┬──────────────────────────────────┘
17 ↓
18┌─────────────────────────────────────────────────────────┐
19│ Layer 3: Integration Methods │
20│ - Plugins (Ratify, Gatekeeper, Containerd) │
21│ - CLI tools (atcr-verify) │
22│ - External services (webhooks, APIs) │
23│ - (Optional) X.509 certificates (hold-as-CA) │
24└──────────────────────┬──────────────────────────────────┘
25 ↓
26┌─────────────────────────────────────────────────────────┐
27│ Layer 2: Signature Discovery │
28│ - OCI Referrers API (GET /v2/.../referrers/...) │
29│ - ORAS artifact format │
30│ - artifactType: application/vnd.atproto.signature... │
31└──────────────────────┬──────────────────────────────────┘
32 ↓
33┌─────────────────────────────────────────────────────────┐
34│ Layer 1: ATProto Signatures (Foundation) │
35│ - Manifests signed by PDS (K-256) │
36│ - Signatures in ATProto repository commits │
37│ - Public keys in DID documents │
38│ - DID-based identity │
39└─────────────────────────────────────────────────────────┘
40```
41
42## Integration Approaches
43
44### Approach 1: Plugin-Based (RECOMMENDED) ⭐
45
46**Best for:** Kubernetes, standard tooling, production deployments
47
48Integrate through plugin systems of existing tools:
49
50#### Ratify Verifier Plugin
51- **Use case:** Kubernetes admission control via Gatekeeper
52- **Effort:** 2-3 weeks to build
53- **Maturity:** CNCF Sandbox project, growing adoption
54- **Benefits:**
55 - ✅ Standard plugin interface
56 - ✅ Works with existing Ratify deployments
57 - ✅ Policy-based enforcement
58 - ✅ Multi-verifier support (can combine with Notation, Cosign)
59
60**Implementation:**
61```go
62// Ratify plugin interface
63type ReferenceVerifier interface {
64 VerifyReference(
65 ctx context.Context,
66 subjectRef common.Reference,
67 referenceDesc ocispecs.ReferenceDescriptor,
68 store referrerStore.ReferrerStore,
69 ) (VerifierResult, error)
70}
71```
72
73**Deployment:**
74```yaml
75apiVersion: config.ratify.deislabs.io/v1beta1
76kind: Verifier
77metadata:
78 name: atcr-verifier
79spec:
80 name: atproto
81 artifactType: application/vnd.atproto.signature.v1+json
82 parameters:
83 trustedDIDs:
84 - did:plc:alice123
85```
86
87See [Ratify Integration Guide](./SIGNATURE_INTEGRATION.md#ratify-plugin)
88
89---
90
91#### OPA Gatekeeper External Provider
92- **Use case:** Kubernetes admission control with OPA policies
93- **Effort:** 2-3 weeks to build
94- **Maturity:** Very stable, widely adopted
95- **Benefits:**
96 - ✅ Rego-based policies (flexible)
97 - ✅ External data provider API (standard)
98 - ✅ Can reuse existing Gatekeeper deployments
99
100**Implementation:**
101```go
102// External data provider
103type Provider struct {
104 verifier *atproto.Verifier
105}
106
107func (p *Provider) Provide(ctx context.Context, req ProviderRequest) (*ProviderResponse, error) {
108 image := req.Keys["image"]
109 result, err := p.verifier.Verify(ctx, image)
110 return &ProviderResponse{
111 Data: map[string]bool{"verified": result.Verified},
112 }, nil
113}
114```
115
116**Policy:**
117```rego
118package verify
119
120violation[{"msg": msg}] {
121 container := input.review.object.spec.containers[_]
122 startswith(container.image, "atcr.io/")
123
124 response := external_data({
125 "provider": "atcr-verifier",
126 "keys": ["image"],
127 "values": [container.image]
128 })
129
130 response.verified != true
131 msg := sprintf("Image %v has no valid ATProto signature", [container.image])
132}
133```
134
135See [Gatekeeper Integration Guide](./SIGNATURE_INTEGRATION.md#opa-gatekeeper-external-provider)
136
137---
138
139#### Containerd 2.0 Image Verifier Plugin
140- **Use case:** Runtime verification at image pull time
141- **Effort:** 1-2 weeks to build
142- **Maturity:** New in Containerd 2.0 (Nov 2024)
143- **Benefits:**
144 - ✅ Runtime enforcement (pull-time verification)
145 - ✅ Works for Docker, nerdctl, ctr
146 - ✅ Transparent to users
147 - ✅ No Kubernetes required
148
149**Limitation:** CRI plugin integration still maturing
150
151**Implementation:**
152```bash
153#!/bin/bash
154# /usr/local/bin/containerd-verifiers/atcr-verifier
155# Binary called by containerd on image pull
156
157# Containerd passes image info via stdin
158read -r INPUT
159
160IMAGE=$(echo "$INPUT" | jq -r '.reference')
161DIGEST=$(echo "$INPUT" | jq -r '.descriptor.digest')
162
163# Verify signature
164if atcr-verify "$IMAGE@$DIGEST" --quiet; then
165 exit 0 # Verified
166else
167 exit 1 # Failed
168fi
169```
170
171**Configuration:**
172```toml
173# /etc/containerd/config.toml
174[plugins."io.containerd.image-verifier.v1.bindir"]
175 bin_dir = "/usr/local/bin/containerd-verifiers"
176 max_verifiers = 5
177 per_verifier_timeout = "10s"
178```
179
180See [Containerd Integration Guide](./SIGNATURE_INTEGRATION.md#containerd-20)
181
182---
183
184### Approach 2: CLI Tool (RECOMMENDED) ⭐
185
186**Best for:** CI/CD, scripts, general-purpose verification
187
188Use `atcr-verify` CLI tool directly in workflows:
189
190#### Command-Line Verification
191```bash
192# Basic verification
193atcr-verify atcr.io/alice/myapp:latest
194
195# With trust policy
196atcr-verify atcr.io/alice/myapp:latest --policy trust-policy.yaml
197
198# JSON output for scripting
199atcr-verify atcr.io/alice/myapp:latest --output json
200
201# Quiet mode for exit codes
202atcr-verify atcr.io/alice/myapp:latest --quiet && echo "Verified"
203```
204
205#### CI/CD Integration
206
207**GitHub Actions:**
208```yaml
209- name: Verify image
210 run: atcr-verify ${{ env.IMAGE }} --policy .github/trust-policy.yaml
211```
212
213**GitLab CI:**
214```yaml
215verify:
216 image: atcr.io/atcr/verify:latest
217 script:
218 - atcr-verify ${IMAGE} --policy trust-policy.yaml
219```
220
221**Universal Container:**
222```bash
223docker run --rm atcr.io/atcr/verify:latest verify IMAGE
224```
225
226**Benefits:**
227- ✅ Works everywhere (not just Kubernetes)
228- ✅ Simple integration (single binary)
229- ✅ No plugin installation required
230- ✅ Offline mode support
231
232See [atcr-verify CLI Documentation](./ATCR_VERIFY_CLI.md)
233
234---
235
236### Approach 3: External Services
237
238**Best for:** Custom admission controllers, API-based verification
239
240Build verification as a service that tools can call:
241
242#### Webhook Service
243```go
244// HTTP endpoint for verification
245func (h *Handler) VerifyImage(w http.ResponseWriter, r *http.Request) {
246 image := r.URL.Query().Get("image")
247
248 result, err := h.verifier.Verify(r.Context(), image)
249 if err != nil {
250 http.Error(w, err.Error(), http.StatusInternalServerError)
251 return
252 }
253
254 json.NewEncoder(w).Encode(map[string]interface{}{
255 "verified": result.Verified,
256 "did": result.Signature.DID,
257 "signedAt": result.Signature.SignedAt,
258 })
259}
260```
261
262#### Usage from Kyverno
263```yaml
264verifyImages:
265- imageReferences:
266 - "atcr.io/*/*"
267 attestors:
268 - entries:
269 - api:
270 url: http://atcr-verify.kube-system/verify?image={{ image }}
271```
272
273**Benefits:**
274- ✅ Flexible integration
275- ✅ Centralized verification logic
276- ✅ Caching and rate limiting
277- ✅ Can add additional checks (vulnerability scanning, etc.)
278
279---
280
281### Approach 4: Hold-as-CA (OPTIONAL, ENTERPRISE ONLY)
282
283**Best for:** Enterprise X.509 PKI compliance requirements
284
285⚠️ **WARNING:** This approach introduces centralization trade-offs. Only use if you have specific X.509 compliance requirements.
286
287Hold services act as Certificate Authorities that issue X.509 certificates for users, enabling standard Notation verification.
288
289**When to use:**
290- Enterprise requires standard X.509 PKI
291- Cannot deploy custom plugins
292- Accept centralization trade-off for tool compatibility
293
294**When NOT to use:**
295- Default deployments (use plugins instead)
296- Maximum decentralization required
297- Don't need X.509 compliance
298
299See [Hold-as-CA Architecture](./HOLD_AS_CA.md) for complete details and security implications.
300
301---
302
303## Tool Compatibility Matrix
304
305| Tool | Discover | Verify | Integration Method | Priority | Effort |
306|------|----------|--------|-------------------|----------|--------|
307| **Kubernetes** | | | | | |
308| OPA Gatekeeper | ✅ | ✅ | External provider | **HIGH** | 2-3 weeks |
309| Ratify | ✅ | ✅ | Verifier plugin | **HIGH** | 2-3 weeks |
310| Kyverno | ✅ | ⚠️ | External service | MEDIUM | 2 weeks |
311| Portieris | ❌ | ❌ | N/A (deprecated) | NONE | - |
312| **Runtime** | | | | | |
313| Containerd 2.0 | ✅ | ✅ | Bindir plugin | **MED-HIGH** | 1-2 weeks |
314| CRI-O | ⚠️ | ⚠️ | Upstream contribution | MEDIUM | 3-4 weeks |
315| Podman | ⚠️ | ⚠️ | Upstream contribution | MEDIUM | 3-4 weeks |
316| **CI/CD** | | | | | |
317| GitHub Actions | ✅ | ✅ | Custom action | **HIGH** | 1 week |
318| GitLab CI | ✅ | ✅ | Container image | **HIGH** | 1 week |
319| Jenkins/CircleCI | ✅ | ✅ | Container image | HIGH | 1 week |
320| **Scanners** | | | | | |
321| Trivy | ✅ | ❌ | N/A (not verifier) | NONE | - |
322| Snyk | ❌ | ❌ | N/A (not verifier) | NONE | - |
323| Anchore | ❌ | ❌ | N/A (not verifier) | NONE | - |
324| **Registries** | | | | | |
325| Harbor | ✅ | ⚠️ | UI integration | LOW | - |
326| **OCI Tools** | | | | | |
327| ORAS CLI | ✅ | ❌ | Already works | Document | - |
328| Notation | ⚠️ | ⚠️ | Hold-as-CA | OPTIONAL | 3-4 weeks |
329| Cosign | ❌ | ❌ | Not compatible | NONE | - |
330| Crane | ✅ | ❌ | Already works | Document | - |
331| Skopeo | ⚠️ | ⚠️ | Upstream contribution | LOW | 3-4 weeks |
332
333**Legend:**
334- ✅ Works / Feasible
335- ⚠️ Partial / Requires changes
336- ❌ Not applicable / Not feasible
337
338---
339
340## Implementation Roadmap
341
342### Phase 1: Foundation (4-5 weeks) ⭐
343
344**Goal:** Core verification capability
345
3461. **atcr-verify CLI tool** (Week 1-2)
347 - ATProto signature verification
348 - Trust policy support
349 - Multiple output formats
350 - Offline mode
351
3522. **OCI Referrers API** (Week 2-3)
353 - AppView endpoint implementation
354 - ORAS artifact serving
355 - Integration with existing SBOM pattern
356
3573. **CI/CD Container Image** (Week 3)
358 - Universal verification image
359 - Documentation for GitHub Actions, GitLab CI
360 - Example workflows
361
3624. **Documentation** (Week 4-5)
363 - Integration guides
364 - Trust policy examples
365 - Troubleshooting guides
366
367**Deliverables:**
368- `atcr-verify` binary (Linux, macOS, Windows)
369- `atcr.io/atcr/verify:latest` container image
370- OCI Referrers API implementation
371- Complete documentation
372
373---
374
375### Phase 2: Kubernetes Integration (3-4 weeks)
376
377**Goal:** Production-ready Kubernetes admission control
378
3795. **OPA Gatekeeper Provider** (Week 1-2)
380 - External data provider service
381 - Helm chart for deployment
382 - Example policies
383
3846. **Ratify Plugin** (Week 2-3)
385 - Verifier plugin implementation
386 - Testing with Ratify
387 - Documentation
388
3897. **Kubernetes Examples** (Week 4)
390 - Deployment manifests
391 - Policy examples
392 - Integration testing
393
394**Deliverables:**
395- `atcr-gatekeeper-provider` service
396- Ratify plugin binary
397- Kubernetes deployment examples
398- Production deployment guide
399
400---
401
402### Phase 3: Runtime Verification (2-3 weeks)
403
404**Goal:** Pull-time verification
405
4068. **Containerd Plugin** (Week 1-2)
407 - Bindir verifier implementation
408 - Configuration documentation
409 - Testing with Docker, nerdctl
410
4119. **CRI-O/Podman Integration** (Week 3, optional)
412 - Upstream contribution (if accepted)
413 - Policy.json extension
414 - Documentation
415
416**Deliverables:**
417- Containerd verifier binary
418- Configuration guides
419- Runtime verification examples
420
421---
422
423### Phase 4: Optional Features (2-3 weeks)
424
425**Goal:** Enterprise features (if demanded)
426
42710. **Hold-as-CA** (Week 1-2, optional)
428 - Certificate generation
429 - Notation signature creation
430 - Trust store distribution
431 - **Only if enterprise customers request**
432
43311. **Advanced Features** (Week 3, as needed)
434 - Signature transparency log
435 - Multi-signature support
436 - Hardware token integration
437
438**Deliverables:**
439- Hold co-signing implementation (if needed)
440- Advanced feature documentation
441
442---
443
444## Decision Matrix
445
446### Which Integration Approach Should I Use?
447
448```
449┌─────────────────────────────────────────────────┐
450│ Are you using Kubernetes? │
451└───────────────┬─────────────────────────────────┘
452 │
453 ┌────────┴────────┐
454 │ │
455 YES NO
456 │ │
457 ↓ ↓
458┌──────────────┐ ┌──────────────┐
459│ Using │ │ CI/CD │
460│ Gatekeeper? │ │ Pipeline? │
461└──────┬───────┘ └──────┬───────┘
462 │ │
463 ┌────┴────┐ ┌────┴────┐
464 YES NO YES NO
465 │ │ │ │
466 ↓ ↓ ↓ ↓
467External Ratify GitHub Universal
468Provider Plugin Action CLI Tool
469```
470
471#### Use OPA Gatekeeper Provider if:
472- ✅ Already using Gatekeeper
473- ✅ Want Rego-based policies
474- ✅ Need flexible policy logic
475
476#### Use Ratify Plugin if:
477- ✅ Using Ratify (or planning to)
478- ✅ Want standard plugin interface
479- ✅ Need multi-verifier support (Notation + Cosign + ATProto)
480
481#### Use atcr-verify CLI if:
482- ✅ CI/CD pipelines
483- ✅ Local development
484- ✅ Non-Kubernetes environments
485- ✅ Want simple integration
486
487#### Use Containerd Plugin if:
488- ✅ Need runtime enforcement
489- ✅ Want pull-time verification
490- ✅ Using Containerd 2.0+
491
492#### Use Hold-as-CA if:
493- ⚠️ Enterprise X.509 PKI compliance required
494- ⚠️ Cannot deploy plugins
495- ⚠️ Accept centralization trade-off
496
497---
498
499## Best Practices
500
501### 1. Start Simple
502
503Begin with CLI tool integration in CI/CD:
504```bash
505# Add to .github/workflows/deploy.yml
506- run: atcr-verify $IMAGE --policy .github/trust-policy.yaml
507```
508
509### 2. Define Trust Policies
510
511Create trust policies early:
512```yaml
513# trust-policy.yaml
514policies:
515 - name: production
516 scope: "atcr.io/*/prod-*"
517 require:
518 signature: true
519 trustedDIDs: [did:plc:devops-team]
520 action: enforce
521```
522
523### 3. Progressive Rollout
524
5251. **Week 1:** Add verification to CI/CD (audit mode)
5262. **Week 2:** Enforce in CI/CD
5273. **Week 3:** Add Kubernetes admission control (audit mode)
5284. **Week 4:** Enforce in Kubernetes
529
530### 4. Monitor and Alert
531
532Track verification metrics:
533- Verification success/failure rates
534- Policy violations
535- Signature coverage (% of images signed)
536
537### 5. Plan for Key Rotation
538
539- Document DID key rotation procedures
540- Test key rotation in non-production
541- Monitor for unexpected key changes
542
543---
544
545## Common Patterns
546
547### Pattern 1: Multi-Layer Defense
548
549```
5501. CI/CD verification (atcr-verify)
551 ↓ (blocks unsigned images from being pushed)
5522. Kubernetes admission (Gatekeeper/Ratify)
553 ↓ (blocks unsigned images from running)
5543. Runtime verification (Containerd plugin)
555 ↓ (blocks unsigned images from being pulled)
556```
557
558### Pattern 2: Trust Policy Inheritance
559
560```yaml
561# Global policy
562trustedDIDs:
563 - did:plc:security-team # Always trusted
564
565# Environment-specific policies
566staging:
567 trustedDIDs:
568 - did:plc:developers # Additional trust for staging
569
570production:
571 trustedDIDs: [] # Only global trust (security-team)
572```
573
574### Pattern 3: Offline Verification
575
576```bash
577# Build environment (online)
578atcr-verify export $IMAGE -o bundle.json
579
580# Air-gapped environment (offline)
581atcr-verify $IMAGE --offline --bundle bundle.json
582```
583
584---
585
586## Migration Guide
587
588### From Docker Content Trust (DCT)
589
590DCT is deprecated. Migrate to ATCR signatures:
591
592**Old (DCT):**
593```bash
594export DOCKER_CONTENT_TRUST=1
595docker push myimage:latest
596```
597
598**New (ATCR):**
599```bash
600# Signatures created automatically on push
601docker push atcr.io/myorg/myimage:latest
602
603# Verify in CI/CD
604atcr-verify atcr.io/myorg/myimage:latest
605```
606
607### From Cosign
608
609Cosign and ATCR signatures can coexist:
610
611**Dual signing:**
612```bash
613# Push to ATCR (ATProto signature automatic)
614docker push atcr.io/myorg/myimage:latest
615
616# Also sign with Cosign (if needed)
617cosign sign atcr.io/myorg/myimage:latest
618```
619
620**Verification:**
621```bash
622# Verify ATProto signature
623atcr-verify atcr.io/myorg/myimage:latest
624
625# Or verify Cosign signature
626cosign verify atcr.io/myorg/myimage:latest --key cosign.pub
627```
628
629---
630
631## Troubleshooting
632
633### Signatures Not Found
634
635**Symptom:** `atcr-verify` reports "no signature found"
636
637**Diagnosis:**
638```bash
639# Check if Referrers API works
640curl "https://atcr.io/v2/OWNER/REPO/referrers/DIGEST"
641
642# Check if signature artifact exists
643oras discover atcr.io/OWNER/REPO:TAG
644```
645
646**Solutions:**
6471. Verify Referrers API is implemented
6482. Re-push image to generate signature
6493. Check AppView logs for signature creation errors
650
651### DID Resolution Fails
652
653**Symptom:** Cannot resolve DID to public key
654
655**Diagnosis:**
656```bash
657# Test DID resolution
658curl https://plc.directory/did:plc:XXXXXX
659
660# Check DID document has verificationMethod
661curl https://plc.directory/did:plc:XXXXXX | jq .verificationMethod
662```
663
664**Solutions:**
6651. Check internet connectivity
6662. Verify DID is valid
6673. Ensure DID document contains public key
668
669### Policy Violations
670
671**Symptom:** Verification fails with "trust policy violation"
672
673**Diagnosis:**
674```bash
675# Verify with verbose output
676atcr-verify IMAGE --policy policy.yaml --verbose
677```
678
679**Solutions:**
6801. Add DID to trustedDIDs list
6812. Check signature age vs. maxAge
6823. Verify policy scope matches image
683
684---
685
686## See Also
687
688- [ATProto Signatures](./ATPROTO_SIGNATURES.md) - Technical foundation
689- [atcr-verify CLI](./ATCR_VERIFY_CLI.md) - CLI tool documentation
690- [Signature Integration](./SIGNATURE_INTEGRATION.md) - Tool-specific guides
691- [Hold-as-CA](./HOLD_AS_CA.md) - X.509 certificate approach (optional)
692- [Examples](../examples/verification/) - Working code examples