From e790a1655166885ce6ad524ccceed0c472b8ee04 Mon Sep 17 00:00:00 2001 From: "octo-sts[bot]" <157150467+octo-sts[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:09:57 -0800 Subject: [PATCH] update chart appVersion to v0.1.245 (#151) Co-authored-by: k4leung4 <16194785+k4leung4@users.noreply.github.com> --- charts/enforce-agent/Chart.yaml | 2 +- charts/enforce-agent/README.md | 2 +- charts/enforce-agent/crds/mcp.crds.yaml | 356 +++++ charts/enforce-agent/crds/tenant.crds.yaml | 898 ++++++++++++ .../templates/enforce-agent.yaml | 1263 ++++++++++++++++- 5 files changed, 2515 insertions(+), 6 deletions(-) diff --git a/charts/enforce-agent/Chart.yaml b/charts/enforce-agent/Chart.yaml index d238187..e942a14 100644 --- a/charts/enforce-agent/Chart.yaml +++ b/charts/enforce-agent/Chart.yaml @@ -8,7 +8,7 @@ description: | Documentation for the chart can be found [here](https://edu.chainguard.dev/chainguard/chainguard-enforce/chainguard-enforce-kubernetes/alternative-installation-methods/). type: application -version: 0.0.111 +version: 0.0.112 appVersion: v0.1.245 keywords: - chainguard diff --git a/charts/enforce-agent/README.md b/charts/enforce-agent/README.md index 445fb26..cbd53c7 100644 --- a/charts/enforce-agent/README.md +++ b/charts/enforce-agent/README.md @@ -2,7 +2,7 @@ -![Version: 0.0.111](https://img.shields.io/badge/Version-0.0.111-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.1.245](https://img.shields.io/badge/AppVersion-v0.1.245-informational?style=flat-square) +![Version: 0.0.112](https://img.shields.io/badge/Version-0.0.112-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.1.245](https://img.shields.io/badge/AppVersion-v0.1.245-informational?style=flat-square) A helm chart for Chainguard's Enforce Agent. diff --git a/charts/enforce-agent/crds/mcp.crds.yaml b/charts/enforce-agent/crds/mcp.crds.yaml index e69de29..2ed6195 100644 --- a/charts/enforce-agent/crds/mcp.crds.yaml +++ b/charts/enforce-agent/crds/mcp.crds.yaml @@ -0,0 +1,356 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: controllers.gulfstream.dev +spec: + scope: Cluster + group: gulfstream.dev + names: + kind: Controller + plural: controllers + singular: controller + categories: + - all + - gulfstream + shortNames: + - gsc + versions: + - name: v1alpha1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: Ready + type: string + jsonPath: ".status.conditions[?(@.type=='Ready')].status" + - name: Reason + type: string + jsonPath: ".status.conditions[?(@.type=='Ready')].reason" + schema: + openAPIV3Schema: + type: object + properties: + spec: + description: Spec holds the desired state of the Controller (from the client). + type: object + properties: + authorized: + description: Authorized conveys the resources that the controller is allowed to access, but doesn't watch to trigger reconciliation. + type: array + items: + type: object + properties: + allowCrossNamespace: + description: AllowCrossNamespace determines whether these resources may be accessed outside of the primary resource's namespace. If the primary resource is cluster-scoped, then this field is irrelevant. If the primary resource is namespace-scoped, then this field must be true to access resources in other namespaces or cluster-scoped resources. + type: boolean + group: + description: Group is the API group of the resources being authorized. + type: string + resources: + description: Resources is the list of resources within the group to authorize. + type: array + items: + type: string + verbs: + description: Verbs is the list of verbs on these resources to authorize. If Verbs is empty, then all verbs are authorized. + type: array + items: + type: string + configs: + type: array + items: + type: object + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + onChanged: + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + delegate: + description: The URL to delegate reconcilitation to, which must implement the gulfstream proto interface. + type: string + primary: + description: Primary conveys the "primary key" resource, in terms of which we orient all reconciliations. + type: object + properties: + group: + type: string + match: + type: array + items: + type: object + properties: + fieldPath: + type: string + value: + type: string + namespace: + description: Namespace is an optional field restricting these resources to a single namespace. + type: string + resource: + type: string + resyncPeriod: + type: string + version: + type: string + secondary: + description: Secondary conveys the resources that are watched and accessed as part of reconciling the primary resources. + type: array + items: + type: object + properties: + group: + type: string + match: + type: array + items: + type: object + properties: + fieldPath: + type: string + value: + type: string + namespace: + description: Namespace is an optional field restricting these resources to a single namespace. + type: string + relationship: + type: string + resource: + type: string + resyncPeriod: + type: string + version: + type: string + status: + description: Status communicates the observed state of the Controller (from the controller). + 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 + observedGeneration: + description: ObservedGeneration is the 'Generation' of the Service that was last processed by the controller. + type: integer + format: int64 +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: webhooks.gulfstream.dev +spec: + scope: Cluster + group: gulfstream.dev + names: + kind: Webhook + plural: webhooks + singular: webhook + categories: + - all + - gulfstream + shortNames: + - gsw + versions: + - name: v1alpha1 + served: true + storage: true + subresources: + status: {} + additionalPrinterColumns: + - name: Ready + type: string + jsonPath: ".status.conditions[?(@.type=='Ready')].status" + - name: Reason + type: string + jsonPath: ".status.conditions[?(@.type=='Ready')].reason" + schema: + openAPIV3Schema: + type: object + properties: + spec: + description: Spec holds the desired state of the Webhook (from the client). + type: object + properties: + authorized: + description: Authorized conveys the resources that the Webhook is allowed to access, but doesn't watch to trigger reconciliation. + type: array + items: + type: object + properties: + allowCrossNamespace: + description: AllowCrossNamespace determines whether these resources may be accessed outside of the primary resource's namespace. If the primary resource is cluster-scoped, then this field is irrelevant. If the primary resource is namespace-scoped, then this field must be true to access resources in other namespaces or cluster-scoped resources. + type: boolean + group: + description: Group is the API group of the resources being authorized. + type: string + resources: + description: Resources is the list of resources within the group to authorize. + type: array + items: + type: string + verbs: + description: Verbs is the list of verbs on these resources to authorize. If Verbs is empty, then all verbs are authorized. + type: array + items: + type: string + configs: + type: array + items: + type: object + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + onChanged: + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + delegate: + description: The URL to delegate reconcilitation to, which must implement the gulfstream proto interface. + type: string + ref: + description: Ref contains a reference to the resource with an embedded webhook configuration. This currently supports MutatingWebhookConfiguration, ValidatingWebhookConfiguration, and CustomResourceDefinition. + type: object + properties: + apiVersion: + description: API version of the referent. + type: string + kind: + description: Kind of the referent. + type: string + name: + description: Name of the referent. Mutually exclusive with Selector. + type: string + namespace: + description: Namespace of the referent. + type: string + selector: + description: Selector of the referents. Mutually exclusive with Name. + 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 + 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 + status: + description: Status communicates the observed state of the Webhook (from the Webhook). + 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 + observedGeneration: + description: ObservedGeneration is the 'Generation' of the Service that was last processed by the controller. + type: integer + format: int64 +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 diff --git a/charts/enforce-agent/crds/tenant.crds.yaml b/charts/enforce-agent/crds/tenant.crds.yaml index e69de29..86e0c8c 100644 --- a/charts/enforce-agent/crds/tenant.crds.yaml +++ b/charts/enforce-agent/crds/tenant.crds.yaml @@ -0,0 +1,898 @@ +# Copyright 2022 The Sigstore Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterimagepolicies.policy.sigstore.dev +spec: + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1beta1 + - v1 + clientConfig: + service: + name: webhook + namespace: gulfstream + path: /conversionwebhooks/policy-conversion + group: policy.sigstore.dev + names: + kind: ClusterImagePolicy + plural: clusterimagepolicies + singular: clusterimagepolicy + categories: + - all + - sigstore + shortNames: + - cip + scope: Cluster + versions: + - name: v1alpha1 + served: true + storage: true + subresources: + status: {} + schema: + openAPIV3Schema: + 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 + 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 + type: + description: Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :) + type: string + predicateType: + description: PredicateType defines which predicate type to verify. Matches cosign verify-attestation options. + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + 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 + 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 + 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 + 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 + 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 + version: + type: string + 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 + 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 + type: + description: Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :) + type: string + 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 + observedGeneration: + description: ObservedGeneration is the 'Generation' of the Service that was last processed by the controller. + type: integer + format: int64 + - name: v1beta1 + served: true + storage: false + subresources: + status: {} + schema: + openAPIV3Schema: + 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 + 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 + type: + description: Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :) + type: string + predicateType: + description: PredicateType defines which predicate type to verify. Matches cosign verify-attestation options. + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + 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 + 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 + 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 + 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 + 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 + version: + type: string + 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 + 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 + type: + description: Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :) + type: string + 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 + observedGeneration: + description: ObservedGeneration is the 'Generation' of the Service that was last processed by the controller. + type: integer + format: int64 +--- +# Copyright 2022 The Sigstore Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: trustroots.policy.sigstore.dev +spec: + conversion: + strategy: None + group: policy.sigstore.dev + names: + kind: TrustRoot + plural: trustroots + singular: trustroot + categories: + - all + - sigstore + scope: Cluster + versions: + - name: v1alpha1 + served: true + storage: true + subresources: + status: {} + schema: + openAPIV3Schema: + 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 + 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 + 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 + uri: + description: The URI at which the CA can be accessed. + type: string + 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 + 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 + 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 + uri: + description: The URI at which the CA can be accessed. + type: string + 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 + observedGeneration: + description: ObservedGeneration is the 'Generation' of the Service that was last processed by the controller. + type: integer + format: int64 +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 diff --git a/charts/enforce-agent/templates/enforce-agent.yaml b/charts/enforce-agent/templates/enforce-agent.yaml index 1000140..462928e 100644 --- a/charts/enforce-agent/templates/enforce-agent.yaml +++ b/charts/enforce-agent/templates/enforce-agent.yaml @@ -1,5 +1,1260 @@ -? NoSuchKeyThe specified key does not exist.
No such object -: us.artifacts.prod-enforce-fabc.appspot.com/yaml/v0.1.245/mcp.yaml
+# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: v1 +kind: Namespace +metadata: + name: gulfstream + labels: + # This is needed by the configmap webhook + gulfstream.dev/release: devel + # Don't run these through cosigned! + policy.sigstore.dev/include: "false" + policy.sigstore.dev/exclude: "true" +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 --- -? NoSuchKeyThe specified key does not exist.
No such object -: us.artifacts.prod-enforce-fabc.appspot.com/yaml/v0.1.245/tenant.yaml
+kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: gulfstream-rbac +aggregationRule: + clusterRoleSelectors: + - matchLabels: + gulfstream.dev/controller: "true" +rules: [] # Rules are automatically filled in by the controller manager. +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: gulfstream-core + labels: + gulfstream.dev/controller: "true" +rules: + # Allow creating events associated with cluster-scoped resources (e.g. our CRDs) + - apiGroups: [""] + resources: ["events"] + verbs: ["create"] + # Needed to watch and load configuration and secret data. + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "update", "watch"] + # Allow the reconciliation of exactly our validating webhooks. + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["list", "watch"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["get", "update"] + resourceNames: ["config.webhook.gulfstream.dev", "validation.webhook.gulfstream.dev"] + # Allow the reconciliation of exactly our mutating webhooks. + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["list", "watch"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["get", "update"] + resourceNames: ["defaulting.webhook.gulfstream.dev"] + # Allow the reconciliation of exactly our CRDs. + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["list", "watch"] + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "update"] + resourceNames: ["controllers.gulfstream.dev", "webhooks.gulfstream.dev"] + # These are the resources that we are controlling. + - apiGroups: ["gulfstream.dev"] + resources: ["*"] + verbs: ["get", "list", "update", "watch"] + # The webhook configured the namespace as the OwnerRef on various cluster-scoped resources, + # which requires we can Get the system namespace. + - apiGroups: [""] + resources: ["namespaces"] + verbs: ["get"] + resourceNames: ["gulfstream"] +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: gulfstream-namespace-rbac + namespace: gulfstream +rules: + # Needed to watch and load configuration and secret data. + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "update", "watch"] +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: controller + namespace: gulfstream +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: gulfstream-rbac +subjects: + - kind: ServiceAccount + name: controller + namespace: gulfstream +roleRef: + kind: ClusterRole + name: gulfstream-rbac + apiGroup: rbac.authorization.k8s.io +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: gulfstream-namespace-rbac + namespace: gulfstream +subjects: + - kind: ServiceAccount + name: controller + namespace: gulfstream +roleRef: + kind: Role + name: gulfstream-namespace-rbac + apiGroup: rbac.authorization.k8s.io +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: meta-controlplane + name: webhook + namespace: gulfstream +spec: + ports: + - name: https-webhook + port: 443 + targetPort: 443 + selector: + app: meta-controlplane +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: defaulting.webhook.gulfstream.dev +webhooks: + - admissionReviewVersions: ["v1"] + clientConfig: + service: + name: webhook + namespace: gulfstream + failurePolicy: Fail + sideEffects: None + timeoutSeconds: 25 + name: defaulting.webhook.gulfstream.dev +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: validation.webhook.gulfstream.dev +webhooks: + - admissionReviewVersions: ["v1"] + clientConfig: + service: + name: webhook + namespace: gulfstream + failurePolicy: Fail + sideEffects: None + timeoutSeconds: 25 + name: validation.webhook.gulfstream.dev +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: config.webhook.gulfstream.dev +webhooks: + - admissionReviewVersions: ["v1"] + clientConfig: + service: + name: webhook + namespace: gulfstream + # This only determines what happens on networking failures, + # which are most likely for this webhook at install-time, so + # tell the API server to ignore those, since they are most + # likely just an install-time race. + failurePolicy: Ignore + sideEffects: None + timeoutSeconds: 25 + name: config.webhook.gulfstream.dev + namespaceSelector: + matchExpressions: + - key: gulfstream.dev/release + operator: Exists +--- +apiVersion: v1 +kind: Secret +metadata: + name: webhook-certs + namespace: gulfstream +# The data is populated at install time. +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-leader-election + namespace: gulfstream + labels: + gulfstream.dev/release: devel +data: + # This should match the controlplane's replica count. + buckets: "2" +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-logging + namespace: gulfstream + labels: + gulfstream.dev/release: devel +data: + loglevel.controlplane: "info" +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-observability + namespace: gulfstream + labels: + gulfstream.dev/release: devel +data: + metrics.backend-destination: prometheus + metrics.request-metrics-backend-destination: prometheus +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: meta-controlplane + namespace: gulfstream +spec: + minAvailable: 1 + selector: + matchLabels: + app: meta-controlplane +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: meta-controlplane + namespace: gulfstream +spec: + # Keep replicas in sync with "buckets" value in config-leader-election.yaml. + replicas: 2 + # We allow things to deploy and update in parallel, but use a + # PodDisruptionBudget (above) to ensure that at least 1 pod remains available + # as we are updating things. This is a delicate balancing act because: + # 1. We need to launch the initial set of pods in "Parallel" so that whichever + # pod ends up the leader of the webhook cert comes up immediately, but + # 2. We cannot update all pods in parallel because this serves a webhook that + # would become unavailable if all the pods were deleted at once. + podManagementPolicy: Parallel + # Wait for 30s before updating the next pod. + minReadySeconds: 30 + updateStrategy: + type: RollingUpdate + selector: + matchLabels: + app: meta-controlplane + serviceName: &service "webhook" + template: + metadata: + labels: + app: meta-controlplane + spec: + # To avoid node becoming SPOF, spread our replicas to different nodes. + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # favor pods on different nodes + - podAffinityTerm: + labelSelector: + matchLabels: + app: meta-controlplane + topologyKey: kubernetes.io/hostname + weight: 100 + # favor pods in different zones + - podAffinityTerm: + labelSelector: + matchLabels: + app: meta-controlplane + topologyKey: "topology.kubernetes.io/zone" + weight: 100 + # Allow this pod to bind to "low" ports without root / capabilities. + # As of Kubernetes 1.22 this is considered a "safe" sysctl according + # to the upstream documentation: + # https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/#enabling-unsafe-sysctls + securityContext: + sysctls: + - name: net.ipv4.ip_unprivileged_port_start + value: "0" + serviceAccountName: controller + containers: + - name: controller + image: us.gcr.io/prod-enforce-fabc/controlplane:v0.1.245@sha256:db22e6f78f3beca73fe5ccf5f050a48f8273884c4ec9bc368e09f30296d97ecd + resources: + requests: + cpu: 50m + memory: 50Mi + limits: + cpu: 1 + memory: 1Gi + ports: + - name: https-webhook + containerPort: 443 + readinessProbe: + periodSeconds: 1 + httpGet: + scheme: HTTPS + port: 443 + httpHeaders: + - name: k-kubelet-probe + value: "meta-controlplane" + livenessProbe: + periodSeconds: 1 + failureThreshold: 50 + httpGet: + scheme: HTTPS + port: 443 + httpHeaders: + - name: k-kubelet-probe + value: "meta-controlplane" + env: + - name: KUBERNETES_MIN_VERSION + value: "1.22.0" + # These settings are used for statefulset-based + # leader selection. + - name: STATEFUL_CONTROLLER_ORDINAL + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: STATEFUL_SERVICE_NAME + value: *service + - name: SYSTEM_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: CONFIG_LOGGING_NAME + value: config-logging + - name: CONFIG_OBSERVABILITY_NAME + value: config-observability + - name: METRICS_DOMAIN + value: gulfstream.dev/meta + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL + # TODO: Once NET_BIND_SERVICE is sufficient to bind low ports, + # switch to adding that capability here. See also: + # https://kubernetes.io/docs/concepts/security/pod-security-standards/ + # add: + # - NET_BIND_SERVICE + volumeMounts: + # To remove the STS process, replace this with oidc-token, + # drop the sidecar, and the sts-token volume below. + - name: sts-token + mountPath: /var/run/gulfstream + - name: sts + # The STS container is responsible for normalizing federated OIDC + # tokens by using `chainctl auth login [...] --refresh` with the + # "sts-in" identity token. + image: us.gcr.io/prod-enforce-fabc/chainctl:v0.1.245@sha256:dd9e9cb180f8e61ffe29bf1efb795ce42d881f111de8da63dd6f2ea8cb9f08ad + readinessProbe: + exec: + command: + - /ko-app/chainctl + - auth + - status + # Don't call any APIs, just do some basic + # token integrity checks. + - --quick + - --audience + - gulfstream + - --output=terse + initialDelaySeconds: 1 + periodSeconds: 5 + args: ["auth", "login", "--audience", "gulfstream", "--identity-token", "/var/run/sts-in/oidc-token", "--gulfstream", + # If GOOGLE_SERVICE_ACCOUNT_NAME is set, prefer that over + # the provided token. + "--prefer-ambient-credentials", + # When INVITE_CODE is populated, failures to exchange tokens + # will cause us to attempt to register this service account + # and cluster using the invite code as authentication. + ] + env: + - name: XDG_CACHE_HOME + value: /var/run/sts-out + - name: SYSTEM_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INVITE_CODE + valueFrom: + secretKeyRef: + name: mcp-creds + key: code + optional: true + - name: IDENTITY_UID + valueFrom: + secretKeyRef: + name: mcp-creds + key: identity-uid + optional: true + - name: ENFORCER_OPTIONS_JSON + value: "" + # Allow users to specify name/description when a cluster first + # registers itself with an invite code. + - name: CHAINGUARD_CLUSTER_NAME + valueFrom: + secretKeyRef: + name: mcp-creds + key: cluster-name + optional: true + - name: CHAINGUARD_CLUSTER_DESCRIPTION + valueFrom: + secretKeyRef: + name: mcp-creds + key: cluster-description + optional: true + # If we mount GCP credentials, this is where we will mount them. + - name: GOOGLE_APPLICATION_CREDENTIALS + valueFrom: + secretKeyRef: + name: mcp-creds + key: gcp-svc-acct-path + optional: true + - name: GOOGLE_SERVICE_ACCOUNT_NAME + valueFrom: + secretKeyRef: + name: mcp-creds + key: gcp-svc-acct-name + optional: true + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL + resources: + requests: + cpu: 50m + memory: 50Mi + limits: + cpu: 1 + memory: 1Gi + volumeMounts: + - mountPath: /var/run/sts-in + name: oidc-token + readOnly: true + - mountPath: /var/run/sts-out/chainguard/gulfstream + name: sts-token + - name: mcp-creds + mountPath: /var/run/sts + readOnly: true + volumes: + - name: sts-token + emptyDir: {} + - name: oidc-token + projected: + sources: + - serviceAccountToken: + path: oidc-token + # 600 is the shortest supported lifespan + expirationSeconds: 600 + audience: gulfstream + - name: mcp-creds + secret: + secretName: mcp-creds + optional: true + items: + - key: gcp.json + path: gcp.json +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-namespaces +spec: + primary: + version: v1 + resource: namespaces + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-deployments +spec: + primary: + group: apps + version: v1 + resource: deployments + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-replicasets +spec: + primary: + group: apps + version: v1 + resource: replicasets + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-statefulsets +spec: + primary: + group: apps + version: v1 + resource: statefulsets + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-daemonsets +spec: + primary: + group: apps + version: v1 + resource: daemonsets + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-cronjobs +spec: + primary: + group: batch + version: v1 + resource: cronjobs + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-jobs +spec: + primary: + group: batch + version: v1 + resource: jobs + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-pods +spec: + primary: + version: v1 + resource: pods + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-nodes +spec: + primary: + version: v1 + resource: nodes + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-ksvc +spec: + primary: + group: serving.knative.dev + version: v1 + resource: services + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-kcfg +spec: + primary: + group: serving.knative.dev + version: v1 + resource: configurations + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-krev +spec: + primary: + group: serving.knative.dev + version: v1 + resource: revisions + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-tekton-pipelinerun +spec: + primary: + group: tekton.dev + version: v1 + resource: pipelineruns + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-tekton-taskrun +spec: + primary: + group: tekton.dev + version: v1 + resource: taskruns + delegate: https://eots-omni.enforce.dev +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: eots-tekton-run +spec: + primary: + group: tekton.dev + version: v1alpha1 + resource: runs + delegate: https://eots-omni.enforce.dev +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +# RBAC granting the gulfstream controller's aggregated cluster role access to the resources needed +# TODO(mattmoor): It would be cool to have the proxy record +# and minimize the RBAC we actually need here. +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: eots + labels: + # Don't install this for agentless where we use IAM + # for access instead. + agentless.chainguard.dev/skip: "true" + # Aggregate into the gulfstream's cluster role. + gulfstream.dev/controller: "true" +rules: + - apiGroups: [""] + resources: ["pods", "namespaces", "nodes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["batch"] + resources: ["cronjobs", "jobs"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps"] + resources: ["daemonsets", "deployments", "replicasets", "statefulsets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["serving.knative.dev"] + resources: ["services", "configurations", "revisions"] + verbs: ["get", "list", "watch"] + - apiGroups: ["tekton.dev"] + resources: ["pipelineruns", "taskruns", "runs"] + verbs: ["get", "list", "watch"] +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: v1 +kind: Namespace +metadata: + name: cosign-system + labels: + policy.sigstore.dev/include: "false" + policy.sigstore.dev/exclude: "true" + # When tenant is also a SAAS, we want to include this label to + # make sure we don't accidentally remove the cosign-system out + # of the service mesh. + # + # This is a nop when the tenant isn't a SAAS, since this + # namespace does not contain a pod. + istio-injection: enabled +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: cosigned-image-policies-rbac + labels: + # Don't install this for agentless where we use IAM + # for access instead. + agentless.chainguard.dev/skip: "true" +rules: + - apiGroups: [""] + resources: ["configmaps", "secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["configmaps"] + resourceNames: ["config-image-policies", "config-sigstore-keys"] + verbs: ["create", "update", "patch"] +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: cosigned-rbac + labels: + # Don't install this for agentless where we use IAM + # for access instead. + agentless.chainguard.dev/skip: "true" + # Aggregate into the gulfstream's cluster role. + gulfstream.dev/controller: "true" +rules: + # Allow the reconciliation of exactly our validating and mutating webhooks. + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["list", "watch"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["get", "update"] + resourceNames: + - "enforcer.chainguard.dev" + - "policy-validation.webhook.policy.sigstore.dev" + - "policy-defaulting.webhook.policy.sigstore.dev" + # ClusterImagePolicy CRD related. + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["list", "watch"] + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "update"] + resourceNames: ["clusterimagepolicies.policy.sigstore.dev", "trustroots.policy.sigstore.dev"] + - apiGroups: ["policy.sigstore.dev"] + resources: ["*"] + # We need patch for finalizers + verbs: ["get", "list", "watch", "patch", "update"] + # For the continuous-verification reconciler + # TODO(#1217): can remove once "namespace" supported in primary + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] + # This is needed by k8schain to support fetching pull secrets attached to pod specs + # or their service accounts. If pull secrets aren't used, the "secrets" below can + # be safely dropped, but the logic will fetch the service account to check for pull + # secrets. + - apiGroups: [""] + resources: ["serviceaccounts", "secrets"] + verbs: ["get"] +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: continuous-verification +spec: + delegate: https://cosigned-continuous-verification.enforce.dev + primary: + version: v1 + resource: configmaps + namespace: cosign-system + match: + - fieldPath: metadata.name + value: config-image-policies + authorized: + # These are required by k8schain + - resources: [serviceaccounts, secrets] + verbs: [get] + allowCrossNamespace: true +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: policy-compiler +spec: + delegate: https://policy-compiler.enforce.dev + primary: + group: policy.sigstore.dev + version: v1alpha1 + resource: clusterimagepolicies + secondary: + # We double this up to prepare for things to cut over, + # so that this isn't a breaking change, but this isn't + # used yet. + - group: policy.sigstore.dev + version: v1beta1 + resource: clusterimagepolicies + - version: v1 + resource: configmaps + namespace: cosign-system + relationship: Reference + - version: v1 + resource: secrets + relationship: Reference + namespace: cosign-system + authorized: + # K8s events + - resources: [events] + verbs: [create] + # Resync when this changes + configs: + - namespace: cosign-system + name: config-image-policies + onChanged: Resync +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: trustroot-compiler +spec: + delegate: https://trustroot-compiler.enforce.dev + primary: + group: policy.sigstore.dev + version: v1alpha1 + resource: trustroots + secondary: + - version: v1 + resource: configmaps + relationship: Reference + namespace: cosign-system + authorized: + # K8s events + - resources: [events] + verbs: [create] + # Resync when this changes + configs: + - namespace: cosign-system + name: config-sigstore-keys + onChanged: Resync +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: cosigned-image-policies-configmaps-rbac + namespace: cosign-system + labels: + # Don't install this for agentless where we use IAM + # for access instead. + agentless.chainguard.dev/skip: "true" +roleRef: + kind: ClusterRole + name: cosigned-image-policies-rbac + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: controller + namespace: gulfstream +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: policy-defaulting.webhook.policy.sigstore.dev +webhooks: + - admissionReviewVersions: ["v1"] + clientConfig: + service: + namespace: gulfstream + name: webhook + # This is where the MCP will host this webhook (see Webhook below) + path: /admissionwebhooks/cosigned-policy-defaulting +{{- if .Values.enforcerOptions.webhookFailOpen }} + failurePolicy: Ignore +{{- else }} + failurePolicy: Fail +{{- end }} + sideEffects: None + name: policy-defaulting.webhook.policy.sigstore.dev + rules: + - apiGroups: ["policy.sigstore.dev"] + apiVersions: ["v1alpha1", "v1beta1"] + operations: ["CREATE", "UPDATE"] + resources: ["clusterimagepolicies/*", "trustroots/*"] +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Webhook +metadata: + name: cosigned-policy-defaulting +spec: + ref: + apiVersion: admissionregistration.k8s.io/v1 + kind: MutatingWebhookConfiguration + name: policy-defaulting.webhook.policy.sigstore.dev + delegate: https://policy-defaulting.enforce.dev +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: policy-validation.webhook.policy.sigstore.dev +webhooks: + - admissionReviewVersions: ["v1"] + clientConfig: + service: + namespace: gulfstream + name: webhook + # This is where the MCP will host this webhook (see Webhook below) + path: /admissionwebhooks/cosigned-policy-validation + failurePolicy: Fail + sideEffects: None + name: policy-validation.webhook.policy.sigstore.dev + rules: + - apiGroups: ["policy.sigstore.dev"] + apiVersions: ["v1alpha1", "v1beta1"] + operations: ["CREATE", "UPDATE"] + resources: ["clusterimagepolicies/*", "trustroots/*"] +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Webhook +metadata: + name: cosigned-policy-validation +spec: + ref: + apiVersion: admissionregistration.k8s.io/v1 + kind: ValidatingWebhookConfiguration + name: policy-validation.webhook.policy.sigstore.dev + # This configMap contains the configuration settings of the PolicyController. + configs: + - namespace: cosign-system + name: config-policy-controller + # The admission webhook uses these to customize its behavior. + delegate: https://policy-validation.enforce.dev +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-image-policies + namespace: cosign-system + annotations: + # Have continuous verification constantly checking for new containers + # subject to policies and reflecting their status to the API. + gulfstream.dev/resync: "10s" +# This is entirely populated by the controller, and if we include the +# _example we see log lines about failing to parse it. +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-policy-controller + namespace: cosign-system +data: +{{- if .Values.enforcerOptions.enableCIPCache }} + dev.chainguard.enable-cip-cache: "true" +{{- end }} + no-match-policy: {{.Values.enforcerOptions.noMatchPolicy}} +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-sigstore-keys + namespace: cosign-system + annotations: + # Just a placeholder here + gulfstream.dev/resync: "3600s" +# This is entirely populated by the controller, and if we include the +# _example we see log lines about failing to parse it. +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Webhook +metadata: + name: policy-conversion +spec: + ref: + apiVersion: apiextensions.k8s.io/v1 + kind: CustomResourceDefinition + name: clusterimagepolicies.policy.sigstore.dev + delegate: https://policy-conversion.enforce.dev +# Copyright 2021 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: enforcer.chainguard.dev +webhooks: + - name: enforcer.chainguard.dev + namespaceSelector: + # The webhook should only apply to things that opt-in + matchExpressions: +{{- if eq .Values.enforcerOptions.namespaceEnforcementMode "opt-out" }} + - key: policy.sigstore.dev/exclude + operator: NotIn +{{- else }} + - key: policy.sigstore.dev/include + operator: In +{{- end }} + values: ["true"] + rules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + - apiGroups: ["apps"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["deployments", "replicasets", "statefulsets", "daemonsets"] + - apiGroups: ["batch"] + apiVersions: ["v1", "v1beta1"] + operations: ["CREATE", "UPDATE"] + resources: ["jobs", "cronjobs"] + admissionReviewVersions: [v1] + clientConfig: + service: + namespace: gulfstream + name: webhook + # This is where the MCP will host this webhook (see Webhook below) + path: /admissionwebhooks/cosigned-resolution +{{- if .Values.enforcerOptions.webhookFailOpen }} + failurePolicy: Ignore +{{- else }} + failurePolicy: Fail +{{- end }} + reinvocationPolicy: IfNeeded + sideEffects: None + timeoutSeconds: 25 +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Webhook +metadata: + name: cosigned-resolution +spec: + ref: + apiVersion: admissionregistration.k8s.io/v1 + kind: MutatingWebhookConfiguration + name: enforcer.chainguard.dev + authorized: + # These resources are accessed as part of image resolution. + - resources: [serviceaccounts, secrets] + verbs: [get] + # Allow access to the verification key in cosign-system + allowCrossNamespace: true + # This contains the serialized ClusterImagePolicy that are used for validating + # admission. + configs: + - namespace: cosign-system + name: config-image-policies + # This contains the serialized ClusterImagePolicy that are used for validating + # admission. + - namespace: cosign-system + name: config-sigstore-keys + - namespace: cosign-system + name: config-policy-controller + delegate: https://cosigned-resolution.enforce.dev +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: enforcer.chainguard.dev +webhooks: + - name: enforcer.chainguard.dev + namespaceSelector: + # The webhook should only apply to things that opt-in + matchExpressions: +{{- if eq .Values.enforcerOptions.namespaceEnforcementMode "opt-out" }} + - key: policy.sigstore.dev/exclude + operator: NotIn +{{- else }} + - key: policy.sigstore.dev/include + operator: In +{{- end }} + values: ["true"] + rules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods", "pods/ephemeralcontainers"] + - apiGroups: ["apps"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["deployments", "replicasets", "statefulsets", "daemonsets"] + - apiGroups: ["batch"] + apiVersions: ["v1", "v1beta1"] + operations: ["CREATE", "UPDATE"] + resources: ["jobs", "cronjobs"] + admissionReviewVersions: [v1] + clientConfig: + service: + namespace: gulfstream + name: webhook + # This is where the MCP will host this webhook (see Webhook below) + path: /admissionwebhooks/cosigned-verification +{{- if .Values.enforcerOptions.webhookFailOpen }} + failurePolicy: Ignore +{{- else }} + failurePolicy: Fail +{{- end }} + sideEffects: None + timeoutSeconds: 25 +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Webhook +metadata: + name: cosigned-verification +spec: + ref: + apiVersion: admissionregistration.k8s.io/v1 + kind: ValidatingWebhookConfiguration + name: enforcer.chainguard.dev + authorized: + # These resources are accessed as part of image resolution. + - resources: [serviceaccounts, secrets] + verbs: [get] + # Allow access to the verification key in cosign-system + allowCrossNamespace: true + # This contains the serialized ClusterImagePolicy that are used for validating + # admission. + configs: + - namespace: cosign-system + name: config-image-policies + # This contains the serialized TrustRoots that are used for validating + # admission. + - namespace: cosign-system + name: config-sigstore-keys + - namespace: cosign-system + name: config-policy-controller + delegate: https://cosigned-verification.enforce.dev +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: policy-distribution-clusterrole-rbac + labels: + # Don't install this for agentless where we use IAM + # for access instead. + agentless.chainguard.dev/skip: "true" +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create", "patch", "delete", "deletecollection"] +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +# RBAC granting the gulfstream controller's aggregated cluster role access to the resources needed +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: policy-distribution-rbac + labels: + # Don't install this for agentless where we use IAM + # for access instead. + agentless.chainguard.dev/skip: "true" + # Aggregate into the gulfstream's cluster role. + gulfstream.dev/controller: "true" +rules: + # We reconcile the gulfstream namespace. + - apiGroups: [""] + resources: ["namespaces"] + verbs: ["get", "list", "watch"] + - apiGroups: ["policy.sigstore.dev"] + resources: ["clusterimagepolicies", "clusterimagepolicies/status"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create", "patch", "delete", "deletecollection"] +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: gulfstream.dev/v1alpha1 +kind: Controller +metadata: + name: policy-distribution +spec: + primary: + version: v1 + resource: namespaces + resyncPeriod: "10s" + match: + - fieldPath: metadata.name + # This namespace is installed when ClusterImagePolicy CRDs is, + # so it should always exist. + value: cosign-system + secondary: + - version: v1 + resource: secrets + namespace: cosign-system + - group: policy.sigstore.dev + version: v1alpha1 + resource: clusterimagepolicies + # We double this up to prepare for things to cut over, + # so that this isn't a breaking change, but this isn't + # used yet. + - group: policy.sigstore.dev + version: v1beta1 + resource: clusterimagepolicies + authorized: + # K8s events + - resources: [events] + verbs: [create] + delegate: https://policy-distribution.enforce.dev +# Copyright 2022 Chainguard, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: policy-distribution-secrets-rbac + namespace: cosign-system + labels: + # Don't install this for agentless where we use IAM + # for access instead. + agentless.chainguard.dev/skip: "true" +roleRef: + kind: ClusterRole + name: policy-distribution-clusterrole-rbac + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: controller + namespace: gulfstream