From 0beccdbd7d23fd522f1c244fb375dbb9cc611a73 Mon Sep 17 00:00:00 2001 From: johanjk Date: Sat, 22 Feb 2025 21:25:57 +0100 Subject: [PATCH] Add cosign policy controller CRDs --- .../clusterimagepolicy_v1alpha1.json | 488 ++++++++++++++++++ .../clusterimagepolicy_v1beta1.json | 488 ++++++++++++++++++ policy.sigstore.dev/trustroot_v1alpha1.json | 226 ++++++++ 3 files changed, 1202 insertions(+) create mode 100644 policy.sigstore.dev/clusterimagepolicy_v1alpha1.json create mode 100644 policy.sigstore.dev/clusterimagepolicy_v1beta1.json create mode 100644 policy.sigstore.dev/trustroot_v1alpha1.json diff --git a/policy.sigstore.dev/clusterimagepolicy_v1alpha1.json b/policy.sigstore.dev/clusterimagepolicy_v1alpha1.json new file mode 100644 index 00000000..7227a77e --- /dev/null +++ b/policy.sigstore.dev/clusterimagepolicy_v1alpha1.json @@ -0,0 +1,488 @@ +{ + "type": "object", + "properties": { + "spec": { + "description": "Spec holds the desired state of the ClusterImagePolicy (from the client).", + "type": "object", + "properties": { + "authorities": { + "description": "Authorities defines the rules for discovering and validating signatures.", + "type": "array", + "items": { + "type": "object", + "properties": { + "attestations": { + "description": "Attestations is a list of individual attestations for this authority, once the signature for this authority has been verified.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "Name of the attestation. These can then be referenced at the CIP level policy.", + "type": "string" + }, + "policy": { + "description": "Policy defines all of the matching signatures, and all of the matching attestations (whose attestations are verified).", + "type": "object", + "properties": { + "configMapRef": { + "description": "ConfigMapRef defines the reference to a configMap with the policy definition.", + "type": "object", + "properties": { + "key": { + "description": "Key defines the key to pull from the configmap.", + "type": "string" + }, + "name": { + "description": "Name is unique within a namespace to reference a configmap resource.", + "type": "string" + }, + "namespace": { + "description": "Namespace defines the space within which the configmap name must be unique.", + "type": "string" + } + }, + "additionalProperties": false + }, + "data": { + "description": "Data contains the policy definition.", + "type": "string" + }, + "fetchConfigFile": { + "description": "FetchConfigFile controls whether ConfigFile will be fetched and made available for CIP level policy evaluation. Note that this only gets evaluated (and hence fetched) iff at least one authority matches. The ConfigFile will then be available in this format: https://github.com/opencontainers/image-spec/blob/main/config.md", + "type": "boolean" + }, + "includeObjectMeta": { + "description": "IncludeObjectMeta controls whether the ObjectMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.", + "type": "boolean" + }, + "includeSpec": { + "description": "IncludeSpec controls whether resource `Spec` will be included and made available for CIP level policy evaluation. Note that this only gets evaluated iff at least one authority matches. Also note that because Spec may be of a different shape depending on the resource being evaluatied (see MatchResource for filtering) you might want to configure these to match the policy file to ensure the shape of the Spec is what you expect when evaling the policy.", + "type": "boolean" + }, + "includeTypeMeta": { + "description": "IncludeTypeMeta controls whether the TypeMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.", + "type": "boolean" + }, + "remote": { + "description": "Remote defines the url to a policy.", + "type": "object", + "properties": { + "sha256sum": { + "description": "Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.", + "type": "string" + }, + "url": { + "description": "URL to the policy data.", + "type": "string" + } + }, + "additionalProperties": false + }, + "type": { + "description": "Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :)", + "type": "string" + } + }, + "additionalProperties": false + }, + "predicateType": { + "description": "PredicateType defines which predicate type to verify. Matches cosign verify-attestation options.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "ctlog": { + "description": "CTLog sets the configuration to verify the authority against a Rekor instance.", + "type": "object", + "properties": { + "trustRootRef": { + "description": "Use the Public Key from the referred TrustRoot.TLog", + "type": "string" + }, + "url": { + "description": "URL sets the url to the rekor instance (by default the public rekor.sigstore.dev)", + "type": "string" + } + }, + "additionalProperties": false + }, + "key": { + "description": "Key defines the type of key to validate the image.", + "type": "object", + "properties": { + "data": { + "description": "Data contains the inline public key.", + "type": "string" + }, + "hashAlgorithm": { + "description": "HashAlgorithm always defaults to sha256 if the algorithm hasn't been explicitly set", + "type": "string" + }, + "kms": { + "description": "KMS contains the KMS url of the public key Supported formats differ based on the KMS system used.", + "type": "string" + }, + "secretRef": { + "description": "SecretRef sets a reference to a secret with the key.", + "type": "object", + "properties": { + "name": { + "description": "name is unique within a namespace to reference a secret resource.", + "type": "string" + }, + "namespace": { + "description": "namespace defines the space within which the secret name must be unique.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "keyless": { + "description": "Keyless sets the configuration to verify the authority against a Fulcio instance.", + "type": "object", + "properties": { + "ca-cert": { + "description": "CACert sets a reference to CA certificate", + "type": "object", + "properties": { + "data": { + "description": "Data contains the inline public key.", + "type": "string" + }, + "hashAlgorithm": { + "description": "HashAlgorithm always defaults to sha256 if the algorithm hasn't been explicitly set", + "type": "string" + }, + "kms": { + "description": "KMS contains the KMS url of the public key Supported formats differ based on the KMS system used.", + "type": "string" + }, + "secretRef": { + "description": "SecretRef sets a reference to a secret with the key.", + "type": "object", + "properties": { + "name": { + "description": "name is unique within a namespace to reference a secret resource.", + "type": "string" + }, + "namespace": { + "description": "namespace defines the space within which the secret name must be unique.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "identities": { + "description": "Identities sets a list of identities.", + "type": "array", + "items": { + "type": "object", + "properties": { + "issuer": { + "description": "Issuer defines the issuer for this identity.", + "type": "string" + }, + "issuerRegExp": { + "description": "IssuerRegExp specifies a regular expression to match the issuer for this identity.", + "type": "string" + }, + "subject": { + "description": "Subject defines the subject for this identity.", + "type": "string" + }, + "subjectRegExp": { + "description": "SubjectRegExp specifies a regular expression to match the subject for this identity.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "insecureIgnoreSCT": { + "description": "InsecureIgnoreSCT omits verifying if a certificate contains an embedded SCT", + "type": "boolean" + }, + "trustRootRef": { + "description": "Use the Certificate Chain from the referred TrustRoot.CertificateAuthorities and TrustRoot.CTLog", + "type": "string" + }, + "url": { + "description": "URL defines a url to the keyless instance.", + "type": "string" + } + }, + "additionalProperties": false + }, + "name": { + "description": "Name is the name for this authority. Used by the CIP Policy validator to be able to reference matching signature or attestation verifications. If not specified, the name will be authority-", + "type": "string" + }, + "rfc3161timestamp": { + "description": "RFC3161Timestamp sets the configuration to verify the signature timestamp against a RFC3161 time-stamping instance.", + "type": "object", + "properties": { + "trustRootRef": { + "description": "Use the Certificate Chain from the referred TrustRoot.TimeStampAuthorities", + "type": "string" + } + }, + "additionalProperties": false + }, + "source": { + "description": "Sources sets the configuration to specify the sources from where to consume the signatures.", + "type": "array", + "items": { + "type": "object", + "properties": { + "oci": { + "description": "OCI defines the registry from where to pull the signature / attestations.", + "type": "string" + }, + "signaturePullSecrets": { + "description": "SignaturePullSecrets is an optional list of references to secrets in the same namespace as the deploying resource for pulling any of the signatures used by this Source.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "tagPrefix": { + "description": "TagPrefix is an optional prefix that signature and attestations have. This is the 'tag based discovery' and in the future once references are fully supported that should likely be the preferred way to handle these.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "static": { + "description": "Static specifies that signatures / attestations are not validated but instead a static policy is applied against matching images.", + "type": "object", + "properties": { + "action": { + "description": "Action defines how to handle a matching policy.", + "type": "string" + }, + "message": { + "description": "For fail actions, emit an optional custom message", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + }, + "images": { + "description": "Images defines the patterns of image names that should be subject to this policy.", + "type": "array", + "items": { + "type": "object", + "properties": { + "glob": { + "description": "Glob defines a globbing pattern.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "match": { + "description": "Match allows selecting resources based on their properties.", + "type": "array", + "items": { + "type": "object", + "properties": { + "group": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "selector": { + "type": "object", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "matchLabels": { + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + } + }, + "additionalProperties": false + }, + "version": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "mode": { + "description": "Mode controls whether a failing policy will be rejected (not admitted), or if errors are converted to Warnings. enforce - Reject (default) warn - allow but warn", + "type": "string" + }, + "policy": { + "description": "Policy is an optional policy that can be applied against all the successfully validated Authorities. If no authorities pass, this does not even get evaluated, as the Policy is considered failed.", + "type": "object", + "properties": { + "configMapRef": { + "description": "ConfigMapRef defines the reference to a configMap with the policy definition.", + "type": "object", + "properties": { + "key": { + "description": "Key defines the key to pull from the configmap.", + "type": "string" + }, + "name": { + "description": "Name is unique within a namespace to reference a configmap resource.", + "type": "string" + }, + "namespace": { + "description": "Namespace defines the space within which the configmap name must be unique.", + "type": "string" + } + }, + "additionalProperties": false + }, + "data": { + "description": "Data contains the policy definition.", + "type": "string" + }, + "fetchConfigFile": { + "description": "FetchConfigFile controls whether ConfigFile will be fetched and made available for CIP level policy evaluation. Note that this only gets evaluated (and hence fetched) iff at least one authority matches. The ConfigFile will then be available in this format: https://github.com/opencontainers/image-spec/blob/main/config.md", + "type": "boolean" + }, + "includeObjectMeta": { + "description": "IncludeObjectMeta controls whether the ObjectMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.", + "type": "boolean" + }, + "includeSpec": { + "description": "IncludeSpec controls whether resource `Spec` will be included and made available for CIP level policy evaluation. Note that this only gets evaluated iff at least one authority matches. Also note that because Spec may be of a different shape depending on the resource being evaluatied (see MatchResource for filtering) you might want to configure these to match the policy file to ensure the shape of the Spec is what you expect when evaling the policy.", + "type": "boolean" + }, + "includeTypeMeta": { + "description": "IncludeTypeMeta controls whether the TypeMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.", + "type": "boolean" + }, + "remote": { + "description": "Remote defines the url to a policy.", + "type": "object", + "properties": { + "sha256sum": { + "description": "Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.", + "type": "string" + }, + "url": { + "description": "URL to the policy data.", + "type": "string" + } + }, + "additionalProperties": false + }, + "type": { + "description": "Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :)", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "status": { + "description": "Status represents the current state of the ClusterImagePolicy. This data may be out of date.", + "type": "object", + "properties": { + "annotations": { + "description": "Annotations is additional Status fields for the Resource to save some additional State as well as convey more information to the user. This is roughly akin to Annotations on any k8s resource, just the reconciler conveying richer information outwards.", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "conditions": { + "description": "Conditions the latest available observations of a resource's current state.", + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "status" + ], + "properties": { + "lastTransitionTime": { + "description": "LastTransitionTime is the last time the condition transitioned from one status to another. We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic differences (all other things held constant).", + "type": "string" + }, + "message": { + "description": "A human readable message indicating details about the transition.", + "type": "string" + }, + "reason": { + "description": "The reason for the condition's last transition.", + "type": "string" + }, + "severity": { + "description": "Severity with which to treat failures of this type of condition. When this is not specified, it defaults to Error.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of condition.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "observedGeneration": { + "description": "ObservedGeneration is the 'Generation' of the Service that was last processed by the controller.", + "type": "integer", + "format": "int64" + } + }, + "additionalProperties": false + } + } +} diff --git a/policy.sigstore.dev/clusterimagepolicy_v1beta1.json b/policy.sigstore.dev/clusterimagepolicy_v1beta1.json new file mode 100644 index 00000000..7227a77e --- /dev/null +++ b/policy.sigstore.dev/clusterimagepolicy_v1beta1.json @@ -0,0 +1,488 @@ +{ + "type": "object", + "properties": { + "spec": { + "description": "Spec holds the desired state of the ClusterImagePolicy (from the client).", + "type": "object", + "properties": { + "authorities": { + "description": "Authorities defines the rules for discovering and validating signatures.", + "type": "array", + "items": { + "type": "object", + "properties": { + "attestations": { + "description": "Attestations is a list of individual attestations for this authority, once the signature for this authority has been verified.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "Name of the attestation. These can then be referenced at the CIP level policy.", + "type": "string" + }, + "policy": { + "description": "Policy defines all of the matching signatures, and all of the matching attestations (whose attestations are verified).", + "type": "object", + "properties": { + "configMapRef": { + "description": "ConfigMapRef defines the reference to a configMap with the policy definition.", + "type": "object", + "properties": { + "key": { + "description": "Key defines the key to pull from the configmap.", + "type": "string" + }, + "name": { + "description": "Name is unique within a namespace to reference a configmap resource.", + "type": "string" + }, + "namespace": { + "description": "Namespace defines the space within which the configmap name must be unique.", + "type": "string" + } + }, + "additionalProperties": false + }, + "data": { + "description": "Data contains the policy definition.", + "type": "string" + }, + "fetchConfigFile": { + "description": "FetchConfigFile controls whether ConfigFile will be fetched and made available for CIP level policy evaluation. Note that this only gets evaluated (and hence fetched) iff at least one authority matches. The ConfigFile will then be available in this format: https://github.com/opencontainers/image-spec/blob/main/config.md", + "type": "boolean" + }, + "includeObjectMeta": { + "description": "IncludeObjectMeta controls whether the ObjectMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.", + "type": "boolean" + }, + "includeSpec": { + "description": "IncludeSpec controls whether resource `Spec` will be included and made available for CIP level policy evaluation. Note that this only gets evaluated iff at least one authority matches. Also note that because Spec may be of a different shape depending on the resource being evaluatied (see MatchResource for filtering) you might want to configure these to match the policy file to ensure the shape of the Spec is what you expect when evaling the policy.", + "type": "boolean" + }, + "includeTypeMeta": { + "description": "IncludeTypeMeta controls whether the TypeMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.", + "type": "boolean" + }, + "remote": { + "description": "Remote defines the url to a policy.", + "type": "object", + "properties": { + "sha256sum": { + "description": "Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.", + "type": "string" + }, + "url": { + "description": "URL to the policy data.", + "type": "string" + } + }, + "additionalProperties": false + }, + "type": { + "description": "Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :)", + "type": "string" + } + }, + "additionalProperties": false + }, + "predicateType": { + "description": "PredicateType defines which predicate type to verify. Matches cosign verify-attestation options.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "ctlog": { + "description": "CTLog sets the configuration to verify the authority against a Rekor instance.", + "type": "object", + "properties": { + "trustRootRef": { + "description": "Use the Public Key from the referred TrustRoot.TLog", + "type": "string" + }, + "url": { + "description": "URL sets the url to the rekor instance (by default the public rekor.sigstore.dev)", + "type": "string" + } + }, + "additionalProperties": false + }, + "key": { + "description": "Key defines the type of key to validate the image.", + "type": "object", + "properties": { + "data": { + "description": "Data contains the inline public key.", + "type": "string" + }, + "hashAlgorithm": { + "description": "HashAlgorithm always defaults to sha256 if the algorithm hasn't been explicitly set", + "type": "string" + }, + "kms": { + "description": "KMS contains the KMS url of the public key Supported formats differ based on the KMS system used.", + "type": "string" + }, + "secretRef": { + "description": "SecretRef sets a reference to a secret with the key.", + "type": "object", + "properties": { + "name": { + "description": "name is unique within a namespace to reference a secret resource.", + "type": "string" + }, + "namespace": { + "description": "namespace defines the space within which the secret name must be unique.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "keyless": { + "description": "Keyless sets the configuration to verify the authority against a Fulcio instance.", + "type": "object", + "properties": { + "ca-cert": { + "description": "CACert sets a reference to CA certificate", + "type": "object", + "properties": { + "data": { + "description": "Data contains the inline public key.", + "type": "string" + }, + "hashAlgorithm": { + "description": "HashAlgorithm always defaults to sha256 if the algorithm hasn't been explicitly set", + "type": "string" + }, + "kms": { + "description": "KMS contains the KMS url of the public key Supported formats differ based on the KMS system used.", + "type": "string" + }, + "secretRef": { + "description": "SecretRef sets a reference to a secret with the key.", + "type": "object", + "properties": { + "name": { + "description": "name is unique within a namespace to reference a secret resource.", + "type": "string" + }, + "namespace": { + "description": "namespace defines the space within which the secret name must be unique.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "identities": { + "description": "Identities sets a list of identities.", + "type": "array", + "items": { + "type": "object", + "properties": { + "issuer": { + "description": "Issuer defines the issuer for this identity.", + "type": "string" + }, + "issuerRegExp": { + "description": "IssuerRegExp specifies a regular expression to match the issuer for this identity.", + "type": "string" + }, + "subject": { + "description": "Subject defines the subject for this identity.", + "type": "string" + }, + "subjectRegExp": { + "description": "SubjectRegExp specifies a regular expression to match the subject for this identity.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "insecureIgnoreSCT": { + "description": "InsecureIgnoreSCT omits verifying if a certificate contains an embedded SCT", + "type": "boolean" + }, + "trustRootRef": { + "description": "Use the Certificate Chain from the referred TrustRoot.CertificateAuthorities and TrustRoot.CTLog", + "type": "string" + }, + "url": { + "description": "URL defines a url to the keyless instance.", + "type": "string" + } + }, + "additionalProperties": false + }, + "name": { + "description": "Name is the name for this authority. Used by the CIP Policy validator to be able to reference matching signature or attestation verifications. If not specified, the name will be authority-", + "type": "string" + }, + "rfc3161timestamp": { + "description": "RFC3161Timestamp sets the configuration to verify the signature timestamp against a RFC3161 time-stamping instance.", + "type": "object", + "properties": { + "trustRootRef": { + "description": "Use the Certificate Chain from the referred TrustRoot.TimeStampAuthorities", + "type": "string" + } + }, + "additionalProperties": false + }, + "source": { + "description": "Sources sets the configuration to specify the sources from where to consume the signatures.", + "type": "array", + "items": { + "type": "object", + "properties": { + "oci": { + "description": "OCI defines the registry from where to pull the signature / attestations.", + "type": "string" + }, + "signaturePullSecrets": { + "description": "SignaturePullSecrets is an optional list of references to secrets in the same namespace as the deploying resource for pulling any of the signatures used by this Source.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "tagPrefix": { + "description": "TagPrefix is an optional prefix that signature and attestations have. This is the 'tag based discovery' and in the future once references are fully supported that should likely be the preferred way to handle these.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "static": { + "description": "Static specifies that signatures / attestations are not validated but instead a static policy is applied against matching images.", + "type": "object", + "properties": { + "action": { + "description": "Action defines how to handle a matching policy.", + "type": "string" + }, + "message": { + "description": "For fail actions, emit an optional custom message", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + }, + "images": { + "description": "Images defines the patterns of image names that should be subject to this policy.", + "type": "array", + "items": { + "type": "object", + "properties": { + "glob": { + "description": "Glob defines a globbing pattern.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "match": { + "description": "Match allows selecting resources based on their properties.", + "type": "array", + "items": { + "type": "object", + "properties": { + "group": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "selector": { + "type": "object", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "matchLabels": { + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + } + }, + "additionalProperties": false + }, + "version": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "mode": { + "description": "Mode controls whether a failing policy will be rejected (not admitted), or if errors are converted to Warnings. enforce - Reject (default) warn - allow but warn", + "type": "string" + }, + "policy": { + "description": "Policy is an optional policy that can be applied against all the successfully validated Authorities. If no authorities pass, this does not even get evaluated, as the Policy is considered failed.", + "type": "object", + "properties": { + "configMapRef": { + "description": "ConfigMapRef defines the reference to a configMap with the policy definition.", + "type": "object", + "properties": { + "key": { + "description": "Key defines the key to pull from the configmap.", + "type": "string" + }, + "name": { + "description": "Name is unique within a namespace to reference a configmap resource.", + "type": "string" + }, + "namespace": { + "description": "Namespace defines the space within which the configmap name must be unique.", + "type": "string" + } + }, + "additionalProperties": false + }, + "data": { + "description": "Data contains the policy definition.", + "type": "string" + }, + "fetchConfigFile": { + "description": "FetchConfigFile controls whether ConfigFile will be fetched and made available for CIP level policy evaluation. Note that this only gets evaluated (and hence fetched) iff at least one authority matches. The ConfigFile will then be available in this format: https://github.com/opencontainers/image-spec/blob/main/config.md", + "type": "boolean" + }, + "includeObjectMeta": { + "description": "IncludeObjectMeta controls whether the ObjectMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.", + "type": "boolean" + }, + "includeSpec": { + "description": "IncludeSpec controls whether resource `Spec` will be included and made available for CIP level policy evaluation. Note that this only gets evaluated iff at least one authority matches. Also note that because Spec may be of a different shape depending on the resource being evaluatied (see MatchResource for filtering) you might want to configure these to match the policy file to ensure the shape of the Spec is what you expect when evaling the policy.", + "type": "boolean" + }, + "includeTypeMeta": { + "description": "IncludeTypeMeta controls whether the TypeMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.", + "type": "boolean" + }, + "remote": { + "description": "Remote defines the url to a policy.", + "type": "object", + "properties": { + "sha256sum": { + "description": "Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.", + "type": "string" + }, + "url": { + "description": "URL to the policy data.", + "type": "string" + } + }, + "additionalProperties": false + }, + "type": { + "description": "Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :)", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "status": { + "description": "Status represents the current state of the ClusterImagePolicy. This data may be out of date.", + "type": "object", + "properties": { + "annotations": { + "description": "Annotations is additional Status fields for the Resource to save some additional State as well as convey more information to the user. This is roughly akin to Annotations on any k8s resource, just the reconciler conveying richer information outwards.", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "conditions": { + "description": "Conditions the latest available observations of a resource's current state.", + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "status" + ], + "properties": { + "lastTransitionTime": { + "description": "LastTransitionTime is the last time the condition transitioned from one status to another. We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic differences (all other things held constant).", + "type": "string" + }, + "message": { + "description": "A human readable message indicating details about the transition.", + "type": "string" + }, + "reason": { + "description": "The reason for the condition's last transition.", + "type": "string" + }, + "severity": { + "description": "Severity with which to treat failures of this type of condition. When this is not specified, it defaults to Error.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of condition.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "observedGeneration": { + "description": "ObservedGeneration is the 'Generation' of the Service that was last processed by the controller.", + "type": "integer", + "format": "int64" + } + }, + "additionalProperties": false + } + } +} diff --git a/policy.sigstore.dev/trustroot_v1alpha1.json b/policy.sigstore.dev/trustroot_v1alpha1.json new file mode 100644 index 00000000..74657e75 --- /dev/null +++ b/policy.sigstore.dev/trustroot_v1alpha1.json @@ -0,0 +1,226 @@ +{ + "type": "object", + "properties": { + "spec": { + "description": "Spec is the definition for a trust root. This is either a TUF root and remote or local repository. You can also bring your own keys/certs here.", + "type": "object", + "properties": { + "remote": { + "description": "Remote specifies initial root of trust & remote mirror.", + "type": "object", + "properties": { + "mirror": { + "description": "Mirror is the remote mirror, for example: https://tuf-repo-cdn.sigstore.dev", + "type": "string" + }, + "root": { + "description": "Root is the base64 encoded, json trusted initial root.", + "type": "string" + }, + "targets": { + "description": "Targets is where the targets live off of the root of the Remote If not specified 'targets' is defaulted.", + "type": "string" + }, + "trustedRootTarget": { + "description": "TrustedRootTarget is the name of the target containing the JSON trusted root. If not specified, `trusted_root.json` is used.", + "type": "string" + } + }, + "additionalProperties": false + }, + "repository": { + "description": "Repository contains the serialized TUF remote repository.", + "type": "object", + "properties": { + "mirrorFS": { + "description": "MirrorFS is the base64 tarred, gzipped, and base64 encoded remote repository that can be used for example in air-gap environments. Will not make outbound network connections, and must then be kept up to date in some other manner. The repository must contain metadata as well as targets.", + "type": "string" + }, + "root": { + "description": "Root is the base64 encoded, json trusted initial root.", + "type": "string" + }, + "targets": { + "description": "Targets is where the targets live off of the root of the Repository above. If not specified 'targets' is defaulted.", + "type": "string" + }, + "trustedRootTarget": { + "description": "TrustedRootTarget is the name of the target containing the JSON trusted root. If not specified, `trusted_root.json` is used.", + "type": "string" + } + }, + "additionalProperties": false + }, + "sigstoreKeys": { + "description": "SigstoreKeys contains the serialized keys.", + "type": "object", + "properties": { + "certificateAuthorities": { + "description": "Trusted certificate authorities (e.g Fulcio).", + "type": "array", + "items": { + "type": "object", + "properties": { + "certChain": { + "description": "The certificate chain for this CA in PEM format. Last entry in this chain is the Root certificate.", + "type": "string" + }, + "subject": { + "description": "The root certificate MUST be self-signed, and so the subject and issuer are the same.", + "type": "object", + "properties": { + "commonName": { + "type": "string" + }, + "organization": { + "type": "string" + } + }, + "additionalProperties": false + }, + "uri": { + "description": "The URI at which the CA can be accessed.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "ctLogs": { + "description": "Certificate Transparency Log", + "type": "array", + "items": { + "type": "object", + "properties": { + "baseURL": { + "description": "The base URL which can be used for URLs for clients.", + "type": "string" + }, + "hashAlgorithm": { + "description": "/ The hash algorithm used for the Merkle Tree", + "type": "string" + }, + "publicKey": { + "description": "PEM encoded public key", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "tLogs": { + "description": "Rekor log specifications", + "type": "array", + "items": { + "type": "object", + "properties": { + "baseURL": { + "description": "The base URL which can be used for URLs for clients.", + "type": "string" + }, + "hashAlgorithm": { + "description": "/ The hash algorithm used for the Merkle Tree", + "type": "string" + }, + "publicKey": { + "description": "PEM encoded public key", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "timestampAuthorities": { + "description": "Trusted timestamping authorities", + "type": "array", + "items": { + "type": "object", + "properties": { + "certChain": { + "description": "The certificate chain for this CA in PEM format. Last entry in this chain is the Root certificate.", + "type": "string" + }, + "subject": { + "description": "The root certificate MUST be self-signed, and so the subject and issuer are the same.", + "type": "object", + "properties": { + "commonName": { + "type": "string" + }, + "organization": { + "type": "string" + } + }, + "additionalProperties": false + }, + "uri": { + "description": "The URI at which the CA can be accessed.", + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "status": { + "description": "Status represents the current state of the TrustRoot. This data may be out of date.", + "type": "object", + "properties": { + "annotations": { + "description": "Annotations is additional Status fields for the Resource to save some additional State as well as convey more information to the user. This is roughly akin to Annotations on any k8s resource, just the reconciler conveying richer information outwards.", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "conditions": { + "description": "Conditions the latest available observations of a resource's current state.", + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "status" + ], + "properties": { + "lastTransitionTime": { + "description": "LastTransitionTime is the last time the condition transitioned from one status to another. We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic differences (all other things held constant).", + "type": "string" + }, + "message": { + "description": "A human readable message indicating details about the transition.", + "type": "string" + }, + "reason": { + "description": "The reason for the condition's last transition.", + "type": "string" + }, + "severity": { + "description": "Severity with which to treat failures of this type of condition. When this is not specified, it defaults to Error.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of condition.", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "observedGeneration": { + "description": "ObservedGeneration is the 'Generation' of the Service that was last processed by the controller.", + "type": "integer", + "format": "int64" + } + }, + "additionalProperties": false + } + } +}