> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Cosign OCI Artifacts

> Shows how to sign and verify OCI artifacts with Cosign and configure Flux to fetch, verify, and deploy signed OCI packages from GHCR using GitOps.

In this lesson you'll sign and verify an OCI artifact with Cosign, then configure Flux to validate signatures when pulling artifacts from an OCI registry (GHCR). This demonstrates end-to-end GitOps delivery with signed OCI packages using Flux's source verification.

Repository context

* Repository: `bb-app-source`
* Branch: `10-demo`
* Manifests folder: `manifests/` (contains namespace, service, deployment YAMLs)
* Deployment image version used in the demo: `7.10.0`

Prerequisites

| Requirement | Purpose / Notes |
| - | - |
| Docker logged into `ghcr.io` | Push/pull artifacts from GitHub Container Registry (use `docker login ghcr.io -u <username>`). |
| `flux` CLI installed | Used for `flux push artifact`, `flux create`, `flux get`, `flux reconcile`. See [Flux CLI docs](https://fluxcd.io/docs/cmd/). |
| `cosign` installed | Used to sign and verify OCI artifacts. See [Cosign docs](https://docs.sigstore.dev/cosign/). |
| Cosign key pair (`cosign.key`, `cosign.pub`) | Private key for signing and public key for verification. Keep the private key secure. |
| Kubernetes cluster with Flux installed | Flux controller running in the `flux-system` namespace. |
| Kubernetes Secrets in `flux-system` | - `ghcr-auth`: `kubernetes.io/dockerconfigjson` for GHCR credentials - `cosign-pub`: contains the Cosign public key used by Flux verify |

Step-by-step

1. Log in to GitHub Container Registry (GHCR) via Docker

```bash theme={null}
# Example: login with username `sidd-harth-2`
docker login ghcr.io -u sidd-harth-2
# Enter a personal access token (PAT) scoped for packages when prompted.
```

2. Create and push an OCI artifact with Flux

From the repository root, push the `manifests/` folder as an OCI artifact. The example below uses a git-substituted short commit hash to create a unique tag:

```bash theme={null}
flux push artifact oci://ghcr.io/sidd-harth-2/bb-app:7.10.0-$(git rev-parse --short HEAD) \
  --path="./manifests" \
  --source="$(git config --get remote.origin.url)" \
  --revision="7.10.0/$(git rev-parse --short HEAD)"
```

Example successful output (summarized):

```text theme={null}
▶ pushing artifact to ghcr.io/sidd-harth-2/bb-app:7.10.0-d6c285f
✓ artifact successfully pushed to ghcr.io/sidd-harth-2/bb-app@sha256:ed0a1401413573b743014d2fdc27953111e33bf8cd51739185ca11baaa0ada81
```

You can pull the pushed tag locally for verification:

```bash theme={null}
docker pull ghcr.io/sidd-harth-2/bb-app:7.10.0-d6c285f
```

For signing and verification, reference the artifact by its digest (sha256). Example digest:

sha256: ed0a1401413573b743014d2fdc27953111e33bf8cd51739185ca11baaa0ada81

3. Sign the pushed artifact with Cosign

Sign the pushed artifact using your Cosign private key (e.g. `../cosign.key`):

```bash theme={null}
cosign sign --key ../cosign.key ghcr.io/sidd-harth-2/bb-app@sha256:ed0a1401413573b743014d2fdc27953111e33bf8cd51739185ca11baaa0ada81
```

Cosign will prompt for the private key password. For private repositories, Cosign also asks to confirm uploading a transparency log entry to Rekor:

```text theme={null}
Enter password for private key:
WARNING: "ghcr.io/sidd-harth-2/bb-app" appears to be a private repository, please confirm uploading to the transparency log at "https://rekor.sigstore.dev"
Are you sure you would like to continue? [y/N] y
```

Example successful output (summarized):

```text theme={null}
tlog entry created with index: 17304303
Pushing signature to: ghcr.io/sidd-harth-2/bb-app:
```

After signing, the signature is stored with the registry as a `.sig` artifact and/or visible in the registry UI.

4. Inspect the pushed signature (optional)

If your registry supports it, you can pull or view the signature blob:

```bash theme={null}
docker pull ghcr.io/sidd-harth-2/bb-app:sha256-ed0a1401413573b743014d2fdc27953111e33bf8cd51739185ca11baaa0ada81.sig
```

Signature metadata and annotations will identify Cosign as the signer and include any OCI labels/annotations present in the image manifest.

5. Verify the artifact locally with the public key

Use the Cosign public key to verify the signature locally:

```bash theme={null}
cosign verify --key ../cosign.pub ghcr.io/sidd-harth-2/bb-app@sha256:ed0a1401413573b743014d2fdc27953111e33bf8cd51739185ca11baaa0ada81
```

Example successful verification output (summarized):

```text theme={null}
Verification for ghcr.io/sidd-harth-2/bb-app@sha256:ed0a1401... --
The following checks were performed on each of these signatures:
 - The cosign claims were validated
 - Existence of the claims in the transparency log was verified offline
 - The signatures were verified against the specified public key
[{"critical": {...}, "optional": {...}}]
```

Note: Cosign supports adding custom claims to signatures. During verification you can validate those claims as part of your policy.

Cosign uploads entries to a public transparency log (Rekor). For private repositories, Cosign will prompt you to consent to uploading the entry. Rekor entries are public and immutable; they contain metadata about the signature and the signing identity or key material (for example, certificate claims when signing with a certificate).

6. Configure Flux to fetch and verify the OCI artifact

Create an `OCIRepository` resource that points to the OCI package and references a Cosign public key stored as a Kubernetes Secret. Flux will fetch the artifact and verify signatures using the configured public key.

Example `OCIRepository`:

```yaml theme={null}
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
  name: 10-demo-source-oci-bb-app
  namespace: flux-system
spec:
  interval: 1m0s
  provider: generic
  ref:
    tag: 7.10.0-d6c285f
  secretRef:
    name: ghcr-auth
  url: oci://ghcr.io/sidd-harth-2/bb-app
  verify:
    provider: cosign
    secretRef:
      name: cosign-pub
```

Create and export the resource with the `flux` CLI:

```bash theme={null}
flux create source oci 10-demo-source-oci-bb-app \
  --url oci://ghcr.io/sidd-harth-2/bb-app \
  --tag 7.10.0-d6c285f \
  --secret-ref ghcr-auth \
  --provider generic \
  --export > 10-demo-source-oci-bb-app.yml
```

Ensure the `ghcr-auth` secret (Docker config JSON) and the Cosign public key secret (`cosign-pub`) exist in the `flux-system` namespace:

```bash theme={null}
kubectl -n flux-system get secret ghcr-auth
# Example output:
# NAME         TYPE                             DATA  AGE
kubectl -n flux-system get secret cosign-pub
# Example output:
# NAME         TYPE    DATA  AGE
# cosign-pub   Opaque  1    14m
```

7. Create a Kustomization to deploy the pulled manifests

Create a `Kustomization` that references the `OCIRepository` source so Flux applies the manifests after the artifact is pulled and verified.

Example `Kustomization`:

```yaml theme={null}
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: 10-demo-kustomize-oci-bb-app
  namespace: flux-system
spec:
  interval: 10s
  path: ./
  prune: true
  sourceRef:
    kind: OCIRepository
    name: 10-demo-source-oci-bb-app
  targetNamespace: 10-demo
```

Generate it with the `flux` CLI:

```bash theme={null}
flux create kustomization 10-demo-kustomize-oci-bb-app \
  --source OCIRepository/10-demo-source-oci-bb-app \
  --target-namespace 10-demo \
  --interval 10s \
  --prune true \
  --export > 10-demo-kustomize-oci-bb-app.yml
```

8. Reconcile and verify Flux source and Kustomization status

After committing and pushing the Flux manifests (or applying them directly), reconcile and inspect status:

```bash theme={null}
# Trigger reconciliation if needed
flux reconcile source git flux-system
```

Check the OCI source and Kustomization status:

```bash theme={null}
flux get sources oci 10-demo-source-oci-bb-app
# Example output:
# NAME                        REVISION                                         SUSPENDED  READY  MESSAGE
flux get kustomizations 10-demo-kustomize-oci-bb-app
# Example output:
# NAME                                   REVISION                                         SUSPENDED  READY  MESSAGE
# 10-demo-kustomize-oci-bb-app           7.10.0-d6c285f@sha256:ed0a1401                 False      True   Applied revision: 7.10.0-d6c285f@sha256:ed0a1401
```

Inspect the `OCIRepository` resource to confirm verification details and conditions:

```bash theme={null}
kubectl -n flux-system get ocirepositories.source.toolkit.fluxcd.io 10-demo-source-oci-bb-app -o yaml
```

In the resource status you should see a `SourceVerified` condition like:

```yaml theme={null}
- lastTransitionTime: "2023-04-06T19:13:00Z"
  message: verified signature of revision 7.10.0-d6c285f@sha256:ed0a1401413573b743014d2fdc27953111e33bf8cd51739185ca11baaa0ada81
  reason: Succeeded
  status: "True"
  type: SourceVerified
```

If signature verification fails, `SourceVerified` will be false and Flux will not apply the unverified artifact.

9. Confirm application deployment

List resources in the target namespace (`10-demo`) and verify the application is running:

```bash theme={null}
kubectl get all -n 10-demo
```

Confirm the demo application (Block Buster) is serving and running the published version (`7.10.0`).

![A browser screenshot of a "BLOCK BUSTER" brick‑breaker game showing colored rows of bricks, a paddle and ball, and a header panel with pod/app info. The game area sits on a starry night background with a green "START GAME" button at the bottom.](https://mintcdn.com/kodekloud-c4ac6d9a/AyhVWHpoMIYCWiei/images/GitOps-with-FluxCD/Secret-Management-Sign-Verification/Demo-Cosign-OCI-Artifacts/blockbuster-brick-breaker-pod-info.jpg?fit=max\&auto=format\&n=AyhVWHpoMIYCWiei\&q=85\&s=2a2d38d5482614dc9e025f6a2c4e4377)

Try playing through the levels — a working gameplay confirms that Flux pulled, verified (via Cosign), and applied the signed OCI artifact successfully.

References and further reading

* Flux: [https://fluxcd.io/](https://fluxcd.io/)
* Flux Source OCI docs: [https://fluxcd.io/docs/components/source/oci/](https://fluxcd.io/docs/components/source/oci/)
* Cosign (Sigstore): [https://docs.sigstore.dev/cosign/](https://docs.sigstore.dev/cosign/)
* Rekor transparency log: [https://rekor.sigstore.dev](https://rekor.sigstore.dev)

That's all for this lesson.

> **[Watch Video](https://learn.kodekloud.com/user/courses/gitops-with-fluxcd/module/c8ad2608-2804-4413-9041-5e8dc9126d53/lesson/3db54ec2-a57f-479e-9fcd-f4ca0717bcce)**

> **[Practice Lab](https://learn.kodekloud.com/user/courses/gitops-with-fluxcd/module/c8ad2608-2804-4413-9041-5e8dc9126d53/lesson/909af89e-e23d-4fdb-ab12-99e20cf7d386)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.