Skip to content

Latest commit

 

History

History
116 lines (85 loc) · 3.76 KB

File metadata and controls

116 lines (85 loc) · 3.76 KB

Deployment Guide

This folder contains the ARM template reference for deploying oa-verifier as an Azure Confidential Container.

Deployment Method

All deployments must use the CI/CD pipeline via GitHub Actions. This ensures:

  1. Reproducible builds with Nix
  2. Proper CCE policy generation with regex patterns for secrets
  3. Sigstore signing for provenance verification
  4. Consistent attestation hashes

CI/CD Pipeline

The build-and-sign workflow handles everything automatically:

  1. Build: Nix builds reproducible container image
  2. Sign: Image signed with Sigstore (keyless, GitHub OIDC)
  3. Push: Published to GHCR and ACR
  4. Policy: CCE policy generated with secret protection (regex patterns)
  5. Deploy: Container deployed to Azure Confidential Containers
  6. Verify: Attestation verified against build

Trigger Deployment

Push to main, or manually trigger:

# Via GitHub CLI
gh workflow run build-and-sign.yml

Files

  • aci-template.json - Reference ARM template (CCE policy generated by CI/CD)

GitHub Secrets Required

Secret Description
ACR_USERNAME Azure Container Registry username
ACR_PASSWORD Azure Container Registry password
AZURE_CREDENTIALS Azure service principal credentials (JSON)
STATION_REGISTRY_URL Station registry service URL
STATION_REGISTRY_SECRET Station registry API secret
CHALLENGE_MIN_INTERVAL Min seconds between privacy checks (default: 300)
CHALLENGE_MAX_INTERVAL Max seconds between privacy checks (default: 600)
SUBMIT_KEY_OWNERSHIP_GRACE_SECONDS Grace window for ownership checks near key expiry (default: 300)

Optional (for custom TLS domain)

Secret Description
TLS_DOMAIN Custom domain for Let's Encrypt cert
ACME_EMAIL Email for Let's Encrypt notifications
ACME_DNS_PROVIDER DNS provider (e.g., cloudflare)
CF_API_TOKEN Cloudflare DNS API token

Creating Azure Credentials

az ad sp create-for-rbac --name "oa-verifier-deploy" \
  --role contributor \
  --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group} \
  --sdk-auth

Verifying the Image

# Verify Sigstore signature
cosign verify ghcr.io/OWNER/oa-verifier@sha256:DIGEST \
  --certificate-identity-regexp='https://github.com/OWNER/REPO/.*' \
  --certificate-oidc-issuer='https://token.actions.githubusercontent.com'

# Verify GitHub attestation
gh attestation verify oci://ghcr.io/OWNER/oa-verifier@sha256:DIGEST --owner OWNER

Note: CI compares attested policy hash against the source-built policy hash. Full JWT signature verification should still be performed by external auditors using the verify_at certificates from /attestation.

Trust Chain

Source Code (GitHub)
    ↓ [Nix reproducible build]
Container Image (signed by Sigstore)
    ↓ [Policy generated from image layers]
CCE Policy (regex patterns for secrets)
    ↓ [SHA256 hash]
Policy Hash (measured by AMD SEV-SNP hardware)
    ↓ [Returned in attestation]
MAA Token (signed by Azure)

Security: Secret Protection in CCE Policy

The CI/CD workflow generates CCE policies with regex patterns for secret environment variables:

// Secrets use regex patterns - actual values NOT in policy
{"pattern": "STATION_REGISTRY_SECRET=.+", "strategy": "re2"}

// Non-secrets use exact matches
{"pattern": "MAA_ENDPOINT=http://localhost:8080/attest/maa", "strategy": "string"}

This ensures:

  • Secret values are never embedded in the CCE policy
  • Policy hash remains constant regardless of secret values
  • Attestation verification works without exposing secrets

Verification

See ../docs/ATTESTATION.md for zero-trust verification instructions.