# GitHub Actions workflow for verifying ATProto signatures name: Verify and Deploy on: push: branches: [main] pull_request: branches: [main] env: REGISTRY: atcr.io IMAGE_NAME: ${{ github.repository }} jobs: verify-signature: name: Verify Image Signature runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up image tag id: vars run: | echo "IMAGE_TAG=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}" >> $GITHUB_OUTPUT - name: Install verification tools run: | # Install ORAS curl -LO https://github.com/oras-project/oras/releases/download/v1.0.0/oras_1.0.0_linux_amd64.tar.gz tar -xzf oras_1.0.0_linux_amd64.tar.gz sudo mv oras /usr/local/bin/ # Install crane curl -sL "https://github.com/google/go-containerregistry/releases/download/v0.15.2/go-containerregistry_Linux_x86_64.tar.gz" > crane.tar.gz tar -xzf crane.tar.gz sudo mv crane /usr/local/bin/ # Install atcr-verify (when available) # curl -LO https://github.com/atcr-io/atcr/releases/latest/download/atcr-verify # chmod +x atcr-verify # sudo mv atcr-verify /usr/local/bin/ - name: Check for signature id: check_signature run: | IMAGE="${{ steps.vars.outputs.IMAGE_TAG }}" echo "Checking signature for $IMAGE" # Get image digest DIGEST=$(crane digest "$IMAGE") echo "Image digest: $DIGEST" # Check for ATProto signature using ORAS REPO=$(echo "$IMAGE" | cut -d: -f1) REFERRERS=$(curl -s "https://${{ env.REGISTRY }}/v2/${REPO#${{ env.REGISTRY }}/}/referrers/${DIGEST}?artifactType=application/vnd.atproto.signature.v1+json") SIG_COUNT=$(echo "$REFERRERS" | jq '.manifests | length') if [ "$SIG_COUNT" -eq 0 ]; then echo "❌ No ATProto signature found" echo "has_signature=false" >> $GITHUB_OUTPUT exit 1 fi echo "✓ Found $SIG_COUNT signature(s)" echo "has_signature=true" >> $GITHUB_OUTPUT - name: Verify signature (full verification) if: steps.check_signature.outputs.has_signature == 'true' run: | IMAGE="${{ steps.vars.outputs.IMAGE_TAG }}" # Option 1: Use atcr-verify CLI (when available) # atcr-verify "$IMAGE" --policy .atcr/trust-policy.yaml # Option 2: Use shell script chmod +x examples/verification/atcr-verify.sh ./examples/verification/atcr-verify.sh "$IMAGE" echo "✓ Signature verified successfully" - name: Verify signer DID if: steps.check_signature.outputs.has_signature == 'true' run: | IMAGE="${{ steps.vars.outputs.IMAGE_TAG }}" # Get signature metadata DIGEST=$(crane digest "$IMAGE") REPO=$(echo "$IMAGE" | cut -d: -f1) REFERRERS=$(curl -s "https://${{ env.REGISTRY }}/v2/${REPO#${{ env.REGISTRY }}/}/referrers/${DIGEST}?artifactType=application/vnd.atproto.signature.v1+json") SIG_DIGEST=$(echo "$REFERRERS" | jq -r '.manifests[0].digest') # Pull signature artifact oras pull "${REPO}@${SIG_DIGEST}" -o /tmp/sig # Extract DID DID=$(jq -r '.atproto.did' /tmp/sig/atproto-signature.json) echo "Signed by DID: $DID" # Check against trusted DIDs TRUSTED_DIDS="${{ secrets.TRUSTED_DIDS }}" # e.g., "did:plc:alice123,did:plc:bob456" if [[ ",$TRUSTED_DIDS," == *",$DID,"* ]]; then echo "✓ DID is trusted" else echo "❌ DID $DID is not in trusted list" exit 1 fi deploy: name: Deploy to Kubernetes needs: verify-signature runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up image tag id: vars run: | echo "IMAGE_TAG=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}" >> $GITHUB_OUTPUT - name: Set up kubectl uses: azure/setup-kubectl@v3 - name: Configure kubectl run: | echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > /tmp/kubeconfig export KUBECONFIG=/tmp/kubeconfig - name: Deploy to production run: | kubectl set image deployment/myapp \ myapp=${{ steps.vars.outputs.IMAGE_TAG }} \ -n production kubectl rollout status deployment/myapp -n production - name: Verify deployment run: | kubectl get pods -n production -l app=myapp # Wait for rollout to complete kubectl wait --for=condition=available --timeout=300s \ deployment/myapp -n production # Alternative: Use atcr-verify action (when available) verify-with-action: name: Verify with ATCR Action runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Verify image signature # uses: atcr-io/atcr-verify-action@v1 # with: # image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} # policy: .atcr/trust-policy.yaml # fail-on-error: true run: | echo "TODO: Use official atcr-verify GitHub Action"