Blob Argo CMP
An Argo CD Config Management Plugin (CMP) for verified manifest delivery from OCI blob archives.
Overview
Blob CMP integrates with the Meigma Blob system to provide cryptographically verified manifest delivery to Argo CD. The plugin verifies blob archives against configurable policies (Sigstore signatures and/or SLSA provenance) before extracting Kubernetes manifests.
Features
- Sigstore verification: Verify keyless signatures from GitHub Actions and other OIDC providers
- SLSA provenance: Validate SLSA build provenance attestations
- Flexible policy configuration: Per-application inline policies or centralized policy management
- Combined verification: Require multiple verification types (e.g., both Sigstore AND SLSA)
- Caching: Built-in caching for tag-to-digest resolution and verified archives
Pushing Manifests
Use blob-action to push Kubernetes manifests to an OCI registry with optional Sigstore signing:
- name: Push manifests id: push uses: meigma/blob-action@v1 with: action: push ref: ghcr.io/${{ github.repository }}/manifests:${{ github.sha }} path: ./manifests sign: "true" # Enable Sigstore keyless signing - name: Generate SLSA attestation uses: actions/attest-build-provenance@v2 with: subject-name: ghcr.io/${{ github.repository }}/manifests subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true
See the integration test workflow for a complete working example.
Installation
1. Deploy the Policy ConfigMap
The policy ConfigMap configures verification requirements and caching:
kubectl apply -f deploy/policy-configmap.yaml
Edit the ConfigMap to configure your verification policies before applying.
2. (Optional) Deploy the Plugin ConfigMap
The plugin configuration is baked into the Docker image, so this step is only needed if you want to customize the plugin parameters:
kubectl apply -f deploy/configmap.yaml
3. Patch argocd-repo-server
Add the CMP sidecar container to the repo-server deployment:
kubectl patch deployment argocd-repo-server -n argocd --patch-file deploy/patch-repo-server.yaml
Or use kubectl edit to add the sidecar container manually. See the Argo CD CMP documentation for details.
Usage
Note: The plugin is named blob-cmp with version v1.0. When referencing it in Applications, use the combined name blob-cmp-v1.0.
Basic Application (Inline Policy)
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: my-app spec: source: repoURL: https://github.com/placeholder/repo path: . plugin: name: blob-cmp-v1.0 parameters: - name: blob-ref string: "ghcr.io/myorg/manifests:v1.2.3" - name: policy string: | type: sigstore sigstore: issuer: "https://token.actions.githubusercontent.com" subject: "https://github.com/myorg/repo/.github/workflows/release.yaml@refs/heads/main" destination: server: https://kubernetes.default.svc namespace: my-app
Policy Types
Sigstore
Verify keyless signatures:
type: sigstore sigstore: issuer: "https://token.actions.githubusercontent.com" subject: "https://github.com/myorg/repo/.github/workflows/release.yaml@refs/heads/main"
SLSA
Verify SLSA provenance:
type: slsa slsa: repository: "myorg/repo" branches: ["main"] tags: ["v*"]
Combined (All)
Require both Sigstore AND SLSA:
type: all policies: - type: sigstore sigstore: issuer: "https://token.actions.githubusercontent.com" subject: "https://github.com/myorg/repo/.github/workflows/release.yaml@refs/heads/main" - type: slsa slsa: repository: "myorg/repo" branches: ["main"]
Combined (Any)
Require Sigstore OR SLSA:
type: any policies: - type: sigstore sigstore: issuer: "https://issuer1" subject: "https://subject1" - type: sigstore sigstore: issuer: "https://issuer2" subject: "https://subject2"
None
Skip verification (for internal registries):
Central Policy Configuration
For environments where inline policies are not desired, configure policies centrally in /etc/blob-cmp/policy.yaml:
apiVersion: blob-cmp.meigma.io/v1alpha1 kind: PolicyConfig # Enable caching for improved performance cache: enabled: true directory: /tmp/blob-cache refTTL: 5m # How long to cache tag->digest mappings # Set to false to reject inline policies allowInlinePolicy: true defaults: requireVerification: true patterns: ["*.yaml", "*.yml", "*.json"] policies: default: type: sigstore sigstore: issuer: "https://token.actions.githubusercontent.com" subject: "https://github.com/myorg/configs/.github/workflows/*" repositories: - match: "ghcr.io/myorg/prod-*" policy: type: all policies: - type: sigstore sigstore: issuer: "https://token.actions.githubusercontent.com" subject: "https://github.com/myorg/prod-configs/.github/workflows/release.yaml@refs/heads/main" - type: slsa slsa: repository: "myorg/prod-configs" branches: ["main"] - match: "internal.registry.io/*" policy: type: none
Using Central Config (No Inline Policy)
apiVersion: argoproj.io/v1alpha1 kind: Application spec: source: plugin: name: blob-cmp-v1.0 parameters: - name: blob-ref string: "ghcr.io/myorg/manifests:v1.2.3" # No policy parameter - uses central config lookup
Parameters
| Parameter | Required | Description |
|---|---|---|
blob-ref |
Yes | OCI reference to blob archive (e.g., ghcr.io/org/repo:tag) |
policy |
No | Inline policy YAML. Overrides central config if set. |
patterns |
No | Glob patterns for manifest files (default: *.yaml, *.yml, *.json) |
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Verification failed (policy violation) |
| 2 | Configuration error |
| 3 | Network/registry error |
| 4 | Invalid archive format |
Complete Example
The integration test workflow demonstrates a complete end-to-end setup:
- Push manifests to GHCR with Sigstore signing using
blob-action - Generate SLSA attestation using
actions/attest-build-provenance - Deploy Argo CD with the CMP sidecar in a Kind cluster
- Create an Application that pulls and verifies the manifests
- Verify deployment succeeds with verified manifests
- Negative test confirms unsigned images are rejected
The workflow configures a policy requiring both Sigstore AND SLSA verification:
policies: repositories: - match: "ghcr.io/myorg/*" policy: type: all policies: - type: sigstore sigstore: issuer: "https://token.actions.githubusercontent.com" subject: "https://github.com/myorg/repo/.github/workflows/release.yml@refs/heads/main" - type: slsa slsa: repository: "myorg/repo"
Building
# Build binary make build # Run tests make test # Build Docker image make docker VERSION=v1.0.0
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.