Skip to content

Feature: Image signing #10

@rhblind

Description

@rhblind

Summary

Sign images with ECDSA keys (cosign-compatible format) to prove authenticity and enable verification by Kubernetes admission controllers.

Motivation

Supply chain security requires image verification. Kubernetes admission controllers (Kyverno, OPA Gatekeeper) can enforce signature verification before allowing image deployment.

Approach

Native key-based signing using Erlang's crypto module. Zero external dependencies. Uses same OCI artifact push mechanism as SBOM.

# Sign with key file
rebar3 ocibuild --push ghcr.io/myorg --sign-key cosign.key

# Or via environment variable
OCIBUILD_SIGN_KEY=/path/to/key.pem rebar3 ocibuild --push ghcr.io/myorg

How It Works

┌─────────────────┐
│  Image Manifest │
│  sha256:abc123  │
└────────┬────────┘
         │ sign with private key (ECDSA P-256)
         ▼
┌─────────────────┐
│   Signature     │──► Push as OCI artifact (referrer)
└─────────────────┘

Implementation Steps

  1. Key loading (ocibuild_sign.erl):

    -spec load_private_key(Path :: file:filename()) ->
        {ok, crypto:key()} | {error, term()}.
    %% Support PEM-encoded ECDSA P-256 keys (cosign default)
  2. Signature generation:

    -spec sign(ManifestDigest :: binary(), PrivateKey :: crypto:key()) ->
        {ok, binary()} | {error, term()}.
    %% Uses crypto:sign/4 with ECDSA P-256 + SHA256
  3. Create signature payload (cosign-compatible format):

    {
      "critical": {
        "identity": {"docker-reference": "ghcr.io/myorg/myapp"},
        "image": {"docker-manifest-digest": "sha256:abc123..."},
        "type": "cosign container image signature"
      },
      "optional": {}
    }
  4. Push as OCI artifact (ocibuild_registry.erl):

    • Reuse referrer push from SBOM
    • artifactType: application/vnd.dev.cosign.simplesigning.v1+json
    • Signature in layer, payload in config
  5. CLI options:

    • --sign-key <path> - path to private key file
    • Config: {sign_key, "/path/to/key.pem"} / sign_key: "/path/to/key.pem"
    • Environment: OCIBUILD_SIGN_KEY

Key Generation

# Generate cosign-compatible key pair
cosign generate-key-pair

# Or with openssl
openssl ecparam -genkey -name prime256v1 -noout -out cosign.key
openssl ec -in cosign.key -pubout -out cosign.pub

Verification

Users verify with cosign:

cosign verify --key cosign.pub ghcr.io/myorg/myapp:latest

Dependencies

  • Depends on Priority 6 (SBOM) for OCI referrer push mechanism

Future Enhancement

Keyless signing via Sigstore/Fulcio (would require HTTP calls to Sigstore services).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions