A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
atcr.io
docker
container
atproto
go
1# ATProto Signature Verification Examples
2
3This directory contains practical examples for verifying ATProto signatures on ATCR container images.
4
5## Files
6
7### Scripts
8
9- **`atcr-verify.sh`** - Standalone signature verification script
10 - Verifies ATProto signatures using shell commands
11 - Requires: `curl`, `jq`, `crane`, `oras`
12 - Does everything except full cryptographic verification
13 - Use this until the `atcr-verify` CLI tool is built
14
15- **`verify-and-pull.sh`** - Secure image pull wrapper
16 - Verifies signatures before pulling images
17 - Can be used as a `docker pull` replacement
18 - Configurable via environment variables
19
20### Configuration
21
22- **`trust-policy.yaml`** - Example trust policy configuration
23 - Defines which DIDs to trust
24 - Specifies policies for different image scopes
25 - Includes audit logging and reporting settings
26
27- **`kubernetes-webhook.yaml`** - Kubernetes admission controller
28 - Validates signatures before pod creation
29 - Includes webhook deployment, service, and configuration
30 - Uses trust policy ConfigMap
31
32## Quick Start
33
34### 1. Verify an Image
35
36```bash
37# Make script executable
38chmod +x atcr-verify.sh
39
40# Verify an image
41./atcr-verify.sh atcr.io/alice/myapp:latest
42```
43
44**Output:**
45```
46═══════════════════════════════════════════════════
47 ATProto Signature Verification
48═══════════════════════════════════════════════════
49 Image: atcr.io/alice/myapp:latest
50═══════════════════════════════════════════════════
51
52[1/7] Resolving image digest...
53 → sha256:abc123...
54[2/7] Discovering ATProto signature artifacts...
55 → Found 1 signature(s)
56 → Signature digest: sha256:sig789...
57 → Signed by DID: did:plc:alice123
58[3/7] Fetching signature metadata...
59 → DID: did:plc:alice123
60 → Handle: alice.bsky.social
61 → PDS: https://bsky.social
62 → Record: at://did:plc:alice123/io.atcr.manifest/abc123
63 → Signed at: 2025-10-31T12:34:56.789Z
64[4/7] Resolving DID to public key...
65 → Public key: zQ3shokFTS3brHcD...
66[5/7] Querying PDS for signed record...
67 → Record CID: bafyreig7...
68[6/7] Verifying record integrity...
69 → Record digest matches image digest
70[7/7] Cryptographic signature verification...
71 ⚠ Full cryptographic verification requires ATProto crypto library
72
73═══════════════════════════════════════════════════
74 ✓ Verification Completed
75═══════════════════════════════════════════════════
76
77 Signed by: alice.bsky.social (did:plc:alice123)
78 Signed at: 2025-10-31T12:34:56.789Z
79 PDS: https://bsky.social
80 Record: at://did:plc:alice123/io.atcr.manifest/abc123
81 Signature: sha256:sig789...
82
83═══════════════════════════════════════════════════
84```
85
86### 2. Secure Pull
87
88```bash
89# Make script executable
90chmod +x verify-and-pull.sh
91
92# Pull image with verification
93./verify-and-pull.sh atcr.io/alice/myapp:latest
94
95# With Docker options
96./verify-and-pull.sh atcr.io/alice/myapp:latest --platform linux/amd64
97```
98
99**Create an alias for convenience:**
100```bash
101# Add to ~/.bashrc or ~/.zshrc
102alias docker-pull-secure='/path/to/verify-and-pull.sh'
103
104# Use it
105docker-pull-secure atcr.io/alice/myapp:latest
106```
107
108### 3. Deploy Kubernetes Webhook
109
110```bash
111# 1. Generate TLS certificates for webhook
112openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt \
113 -days 365 -nodes -subj "/CN=atcr-verify-webhook.atcr-system.svc"
114
115# 2. Create namespace and secret
116kubectl create namespace atcr-system
117kubectl create secret tls atcr-verify-webhook-certs \
118 --cert=tls.crt --key=tls.key -n atcr-system
119
120# 3. Update CA bundle in kubernetes-webhook.yaml
121cat tls.crt | base64 -w 0
122# Copy output and replace caBundle in kubernetes-webhook.yaml
123
124# 4. Deploy webhook
125kubectl apply -f kubernetes-webhook.yaml
126
127# 5. Enable verification for a namespace
128kubectl label namespace production atcr-verify=enabled
129
130# 6. Test with a pod
131kubectl run test-pod --image=atcr.io/alice/myapp:latest -n production
132```
133
134## Prerequisites
135
136### For Scripts
137
138Install required tools:
139
140**macOS (Homebrew):**
141```bash
142brew install curl jq crane oras
143```
144
145**Linux (apt):**
146```bash
147# curl and jq
148sudo apt-get install curl jq
149
150# crane
151curl -sL "https://github.com/google/go-containerregistry/releases/download/v0.15.2/go-containerregistry_Linux_x86_64.tar.gz" | tar -xz crane
152sudo mv crane /usr/local/bin/
153
154# oras
155curl -LO "https://github.com/oras-project/oras/releases/download/v1.0.0/oras_1.0.0_linux_amd64.tar.gz"
156tar -xzf oras_1.0.0_linux_amd64.tar.gz
157sudo mv oras /usr/local/bin/
158```
159
160### For Kubernetes Webhook
161
162Requirements:
163- Kubernetes cluster (1.16+)
164- `kubectl` configured
165- Permission to create namespaces and webhooks
166- Webhook container image (build from source or use pre-built)
167
168## Configuration
169
170### Environment Variables (verify-and-pull.sh)
171
172- `VERIFY_SCRIPT` - Path to atcr-verify.sh (default: ./atcr-verify.sh)
173- `TRUST_POLICY` - Path to trust policy (default: ./trust-policy.yaml)
174- `REQUIRE_VERIFICATION` - Require verification (default: true)
175- `SKIP_ATCR_IMAGES` - Skip verification for non-ATCR images (default: false)
176
177**Example:**
178```bash
179# Skip verification for non-ATCR images
180SKIP_ATCR_IMAGES=true ./verify-and-pull.sh docker.io/library/nginx:latest
181
182# Allow pulling even if verification fails (NOT RECOMMENDED)
183REQUIRE_VERIFICATION=false ./verify-and-pull.sh atcr.io/alice/myapp:latest
184```
185
186### Trust Policy
187
188Edit `trust-policy.yaml` to customize:
189
1901. **Add your DIDs:**
191 ```yaml
192 trustedDIDs:
193 did:plc:your-did:
194 name: "Your Name"
195 validFrom: "2024-01-01T00:00:00Z"
196 ```
197
1982. **Define policies:**
199 ```yaml
200 policies:
201 - name: my-policy
202 scope: "atcr.io/myorg/*"
203 require:
204 signature: true
205 trustedDIDs:
206 - did:plc:your-did
207 action: enforce
208 ```
209
2103. **Use with verification:**
211 ```bash
212 # When atcr-verify CLI is available:
213 atcr-verify IMAGE --policy trust-policy.yaml
214 ```
215
216## Integration Patterns
217
218### CI/CD (GitHub Actions)
219
220```yaml
221- name: Verify image signature
222 run: |
223 chmod +x examples/verification/atcr-verify.sh
224 ./examples/verification/atcr-verify.sh ${{ env.IMAGE }}
225
226- name: Deploy if verified
227 if: success()
228 run: kubectl set image deployment/app app=${{ env.IMAGE }}
229```
230
231### CI/CD (GitLab CI)
232
233```yaml
234verify:
235 script:
236 - chmod +x examples/verification/atcr-verify.sh
237 - ./examples/verification/atcr-verify.sh $IMAGE
238
239deploy:
240 dependencies: [verify]
241 script:
242 - kubectl set image deployment/app app=$IMAGE
243```
244
245### Docker Alias
246
247```bash
248# ~/.bashrc or ~/.zshrc
249function docker() {
250 if [ "$1" = "pull" ] && [[ "$2" =~ ^atcr\.io/ ]]; then
251 echo "Using secure pull with signature verification..."
252 /path/to/verify-and-pull.sh "${@:2}"
253 else
254 command docker "$@"
255 fi
256}
257```
258
259### Systemd Service
260
261```ini
262# /etc/systemd/system/myapp.service
263[Unit]
264Description=My Application
265After=docker.service
266
267[Service]
268Type=oneshot
269ExecStartPre=/path/to/verify-and-pull.sh atcr.io/myorg/myapp:latest
270ExecStart=/usr/bin/docker run atcr.io/myorg/myapp:latest
271Restart=on-failure
272
273[Install]
274WantedBy=multi-user.target
275```
276
277## Troubleshooting
278
279### "No ATProto signature found"
280
281**Cause:** Image doesn't have a signature artifact
282
283**Solutions:**
2841. Check if image exists: `crane digest IMAGE`
2852. Re-push image to generate signature
2863. Verify referrers API is working:
287 ```bash
288 curl "https://atcr.io/v2/REPO/referrers/DIGEST"
289 ```
290
291### "Failed to resolve DID"
292
293**Cause:** DID resolution failed
294
295**Solutions:**
2961. Check internet connectivity
2972. Verify DID is valid: `curl https://plc.directory/DID`
2983. Check if DID document has verificationMethod
299
300### "Failed to fetch record from PDS"
301
302**Cause:** PDS is unreachable or record doesn't exist
303
304**Solutions:**
3051. Check PDS endpoint: `curl PDS_URL/xrpc/com.atproto.server.describeServer`
3062. Verify record URI is correct
3073. Check if record exists in PDS
308
309### Webhook Pods Don't Start
310
311**Cause:** Webhook is rejecting all pods
312
313**Solutions:**
3141. Check webhook logs: `kubectl logs -n atcr-system -l app=atcr-verify-webhook`
3152. Disable webhook temporarily: `kubectl delete validatingwebhookconfiguration atcr-verify`
3163. Fix issue and re-deploy
3174. Test with labeled namespace first
318
319## Security Best Practices
320
3211. **Always verify in production**
322 - Enable webhook for production namespaces
323 - Set `failurePolicy: Fail` to block on errors
324
3252. **Use trust policies**
326 - Define specific trusted DIDs
327 - Don't trust all signatures blindly
328 - Set expiration dates for temporary access
329
3303. **Monitor verification**
331 - Enable audit logging
332 - Review verification failures
333 - Track signature coverage
334
3354. **Rotate keys regularly**
336 - Update DID documents when keys change
337 - Revoke compromised keys immediately
338 - Monitor for unexpected key changes
339
3405. **Secure webhook deployment**
341 - Use TLS for webhook communication
342 - Restrict webhook RBAC permissions
343 - Keep webhook image updated
344
345## Next Steps
346
3471. **Test verification** with your images
3482. **Customize trust policy** for your organization
3493. **Deploy webhook** to test clusters first
3504. **Monitor** verification in CI/CD pipelines
3515. **Gradually roll out** to production
352
353## See Also
354
355- [ATProto Signatures](../../docs/ATPROTO_SIGNATURES.md) - Technical details
356- [Signature Integration](../../docs/SIGNATURE_INTEGRATION.md) - Integration guide
357- [SBOM Scanning](../../docs/SBOM_SCANNING.md) - Similar ORAS pattern
358
359## Support
360
361For issues or questions:
362- GitHub Issues: https://github.com/your-org/atcr/issues
363- Documentation: https://docs.atcr.io
364- Security: security@yourorg.com