Skip to main content

Verify Image Signature with Sigstore Cosign

This page describes the support for validating images using Sigstore Cosign with Styra. DAS users can configure a cosign Policy Library snippet with parameters similar to the ones supported by the cosign CLI tool. The OPA Webhook then performs cosign validation on AdmissionReview objects that contain any image references.

The Policy Snippet leverages an API hosted on the Styra Local Plane sidecar to perform the cosign validation.

DO NOT USE IN PRODUCTION

This experimental policy snippet is under active development and is expected to change in both behavior and interface. Changes will likely require manual migration.

Details

Prevents deployment of containers without a valid signature that is verified using Cosign according to user configuration. The configuration (see sample and schema below) may define, for each registry host and each image path within a registry host, the Cosign verification parameters used to verify the signature of the image. In addition, the configuration may define for each registry host the image paths that are allowed without verification. All other images are prohibited from running.

tip

A glob pattern may be used as an image path configuration to match a range of image paths.

Parameters

  • verification_config

    • Type: Rego reference to an object (example: data.cosign_config).
    • A sample object and JSON schema are given below.
    • This value must be a Rego reference (such as data.cosign_config referring to a datasource or cosign_config referring to a variable) rather than an inline Rego object.
      • Correct usage example:
        cosign_config := {
        "allow_with_verification": { ... },
        "allow_without_verification": { ... }
        }
        parameters := {
        "verification_config": cosign_config
        }
      • Incorrect usage example:
        parameters := {
        "verification_config": {
        "allow_with_verification": { ... },
        "allow_without_verification": { ... }
        }
        }
  • Required Parameters: verification_config

Resource Types

Cosign verification_config object sample

Sample JSON object for the 'verification_config' parameter
{
"allow_with_verification": {
"docker.io": {
"ubuntu/nginx": {
"certificate-identity": "maintainer@example.com",
"certificate-oidc-issuer": "https://github.com/login/oauth"
},
"openpolicyagent/opa": {
"certificate-identity-regexp": ".*@example.com",
"certificate-oidc-issuer-regexp": "https://github.com.*"
}
},
"ecr.io": {
"xyz/busybox": {
"key": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlyx6GRM389JvhDuFEoWC5Mkyeaa\nGsdZQ5Qcw1rmV8I9s+tfh8MMhHtzsGnDg0QMOG2wRPblwVWlT5RfCyDMfg==\n-----END PUBLIC KEY-----",
"insecure-ignore-tlog": true,
"insecure-ignore-sct": true
}
},
"gcr.io": {
"xyz/*": {
"key": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFlyx6GRM389JvhDuFEoWC5Mkyeaa\nGsdZQ5Qcw1rmV8I9s+tfh8MMhHtzsGnDg0QMOG2wRPblwVWlT5RfCyDMfg==\n-----END PUBLIC KEY-----"
}
}
},
"allow_without_verification": {
"docker.io": [
"ubuntu",
"ubuntu/*"
],
"ecr.io": [
"xyz/*"
],
"gcr.io": [
"my-proj-*/base-*-image"
]
}
}
note

The usage of the Cosign verification parameters generally correspond to their CLI behavior. An exception is the key parameter; this parameter currently requires a string containing a public key given in a PEM format (as shown in the sample object above).

caution

If an image path matches both the configuration in allow_with_verification and the configuration in allow_without_verification, the verification behavior is defined by the configuration in allow_with_verification. For instance, in the sample verification_config above, the image docker.io/ubuntu/nginx would match both the ubuntu/nginx path in allow_with_verification and the ubuntu/* path pattern in allow_without_verification. In this case, the image will be verified according to the verification parameters in the allow_with_verification; the configuration in allow_without_verification has no effect for this image.

caution

It is highly recommended that all image path patterns under a single image registry host name be mutually exclusive. In case an image path matches more than one verification configuration, only one verification will be attempted, with no guarantee on which verification configuration is used applied. For example, in the sample configuration below, there is no guarantee whether docker.io/ubuntu/nginx would be verified as signed by "alice@example.com" or by "bob@example.com".

{
"allow_with_verification": {
"docker.io": {
"ubuntu/nginx": {
"certificate-identity": "alice@example.com",
"certificate-oidc-issuer": "https://github.com/login/oauth"
},
"ubuntu/*": {
"certificate-identity": "bob@example.com",
"certificate-oidc-issuer": "https://github.com/login/oauth"
}
}
}
}

Known Limitations of Cosign Validation Snippet v0_0_1

  • The snippet does not produce accurate results in Styra DAS Editor's Preview and Validate mode as it relies on communication with an in-cluster Styra Local Plane (SLP) container. It can produce correct output in Decision Replay mode if the underlying HTTP call to SLP isn't altered. Nevertheless, it is safer to rely on the decisions emitted from in-cluster OPAs to estimate the impact of this snippet. For this reason, it is recommended to verify this snippet as a Monitor rule before promoting it to Enforce.
  • The snippet does not support Repository Authentication. The SLP container is expected to be bootstrapped in an in-cluster environment where it can reach the repository where the Cosign artifact signatures are stored.
  • There is no support for priority between multiple image pattern matches.
  • The snippet supports key-based or keyless verifications only. It does not support verification with a Certificate or Certificate Chain.
  • The cosign verification API embedded in SLP may timeout if the workload contains a large number of images. During testing, the likelihood of this scenario increased if more than 8 containers were referenced in the workload. In this scenario, the snippet will raise a violation with "SLP not available" and OPA will record a DENIED decision.
  • Additionally, a timeout may also occur between the Kubernetes API and the OPA Validating Webhook. Based on the configuration of the OPA Validating Webhook, it may either Fail Open or Fail Close the decision. Depending on the sequencing, this timeout may not be recorded in OPA, may not be recorded by OPA, however, it should be present in the Audit Logging for the Kubernetes cluster.

Cosign verification_config JSON schema

JSON schema that defines the expected format of the 'verification_config' parameter
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "Verification config",
"type": "object",
"properties": {
"allow_with_verification": {
"title": "Config to allow images with verification",
"description": "Each property key is a string that specifies the applicable image registry host (e.g. docker.io). Each property value is an object that specifies the image paths within this registry host to allow with the configured verification.",
"type": "object",
"additionalProperties": {
"title": "Config for each image registry host",
"type": "object",
"additionalProperties": {
"title": "Config for each image path within a registry",
"description": "Each property key is a string (glob pattern supported) that specifies the applicable image path. Each property value is an object that specifies the Cosign parameters to use in verifying an image satisfying this path (pattern).",
"type": "object",
"minProperties": 1,
"properties": {
"key": {
"type": "string"
},
"certificate-identity": {
"type": "string"
},
"certificate-oidc-issuer": {
"type": "string",
"format": "uri"
},
"certificate-identity-regexp": {
"type": "string"
},
"certificate-oidc-issuer-regexp": {
"type": "string"
},
"insecure-ignore-tlog": {
"type": "boolean"
},
"insecure-ignore-sct": {
"type": "boolean"
}
},
"additionalProperties": false
}
}
},
"allow_without_verification": {
"title": "Config to allow images without verification",
"type": "object",
"additionalProperties": {
"title": "Config for each image registry host",
"description": "Each property key is a string that specifies the applicable image registry host (e.g. docker.io). Each property value is an array that specifies within its registry host the collection of applicable image paths to allow without verification.",
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
}
}
},
"minProperties": 1,
"additionalProperties": false
}