diff --git a/charts/supply-chain/templates/_helpers.tpl b/charts/supply-chain/templates/_helpers.tpl index e3d23e02..156de036 100644 --- a/charts/supply-chain/templates/_helpers.tpl +++ b/charts/supply-chain/templates/_helpers.tpl @@ -93,7 +93,6 @@ Sigstore environment variables used in Pipeline Tasks value: $(params.ca-file) - name: COSIGN_YES value: "true" -{{- if eq .Values.rhtas.oidc.enabled true }} - name: OIDC_IDENTITY value: $(params.oidc-identity) - name: OIDC_ISSUER @@ -106,6 +105,7 @@ Sigstore environment variables used in Pipeline Tasks value: $(params.oidc-issuer) - name: SIGSTORE_OIDC_ISSUER value: $(params.oidc-issuer) +{{- if eq .Values.rhtas.oidc.enabled true }} - name: OIDC_CLIENT_ID value: $(params.rhtas-oidc-client-id) - name: COSIGN_OIDC_CLIENT_ID @@ -135,11 +135,11 @@ Sigstore params used in Pipeline Tasks value: $(params.tuf-url) - name: cli-server-url value: $(params.cli-server-url) -{{- if eq .Values.rhtas.oidc.enabled true }} - name: oidc-identity value: $(params.oidc-identity) - name: oidc-issuer value: $(params.oidc-issuer) +{{- if eq .Values.rhtas.oidc.enabled true }} - name: rhtas-oidc-client-id value: $(params.rhtas-oidc-client-id) {{- end }} @@ -164,13 +164,13 @@ Sigstore params descriptions used in Pipeline Tasks - description: Cosign CLI server URL name: cli-server-url type: string -{{- if eq .Values.rhtas.oidc.enabled true }} - description: OIDC identity in signatures name: oidc-identity type: string - description: OIDC issuer in signatures name: oidc-issuer type: string +{{- if eq .Values.rhtas.oidc.enabled true }} - description: RHTAS OIDC client ID name: rhtas-oidc-client-id type: string diff --git a/charts/tekton-chains/Chart.yaml b/charts/tekton-chains/Chart.yaml new file mode 100644 index 00000000..858878a5 --- /dev/null +++ b/charts/tekton-chains/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +name: tekton-chains +description: Tekton Chains configuration for OpenShift Pipelines supply chain security with RHTAS keyless signing +type: application +version: 0.1.0 +appVersion: "1.15.0" +keywords: + - tekton-chains + - supply-chain-security + - sigstore + - in-toto + - slsa + - zero-trust + - openshift-pipelines +maintainers: + - name: Zero Trust Validated Patterns Team + email: ztvp-arch-group@redhat.com diff --git a/charts/tekton-chains/templates/_helpers.tpl b/charts/tekton-chains/templates/_helpers.tpl new file mode 100644 index 00000000..52a669ab --- /dev/null +++ b/charts/tekton-chains/templates/_helpers.tpl @@ -0,0 +1,52 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "tekton-chains.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "tekton-chains.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "tekton-chains.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "tekton-chains.labels" -}} +helm.sh/chart: {{ include "tekton-chains.chart" . }} +{{ include "tekton-chains.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/part-of: tekton-chains +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "tekton-chains.selectorLabels" -}} +app.kubernetes.io/name: {{ include "tekton-chains.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/charts/tekton-chains/templates/tektonconfig-chains.yaml b/charts/tekton-chains/templates/tektonconfig-chains.yaml new file mode 100644 index 00000000..9edb3520 --- /dev/null +++ b/charts/tekton-chains/templates/tektonconfig-chains.yaml @@ -0,0 +1,100 @@ +{{- if .Values.chains.enabled }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: tekton-chains-config + namespace: {{ .Release.Namespace }} + annotations: + argocd.argoproj.io/sync-wave: "47" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: tekton-chains-config + annotations: + argocd.argoproj.io/sync-wave: "47" +rules: +- apiGroups: ["operator.tekton.dev"] + resources: ["tektonconfigs"] + verbs: ["get", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tekton-chains-config + annotations: + argocd.argoproj.io/sync-wave: "47" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-chains-config +subjects: +- kind: ServiceAccount + name: tekton-chains-config + namespace: {{ .Release.Namespace }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: configure-tekton-chains + namespace: {{ .Release.Namespace }} + annotations: + argocd.argoproj.io/sync-wave: "47" + argocd.argoproj.io/hook: PostSync + argocd.argoproj.io/hook-delete-policy: BeforeHookCreation + labels: + {{- include "tekton-chains.labels" . | nindent 4 }} +spec: + backoffLimit: 10 + template: + metadata: + labels: + {{- include "tekton-chains.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: tekton-chains-config + restartPolicy: Never + containers: + - name: configure-chains + image: registry.redhat.io/openshift4/ose-cli:latest + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + cpu: 200m + memory: 256Mi + command: ["/bin/bash", "-c"] + args: + - | + set -euo pipefail + echo "Patching TektonConfig with Chains configuration..." + oc patch tektonconfig config --type=merge -p '{ + "spec": { + "chain": { + "artifacts.taskrun.format": "{{ .Values.chains.artifacts.taskrun.format }}", + "artifacts.taskrun.storage": "{{ .Values.chains.artifacts.taskrun.storage }}", + "artifacts.taskrun.signer": "{{ .Values.chains.artifacts.taskrun.signer }}", + "artifacts.pipelinerun.format": "{{ .Values.chains.artifacts.pipelinerun.format }}", + "artifacts.pipelinerun.storage": "{{ .Values.chains.artifacts.pipelinerun.storage }}", + "artifacts.pipelinerun.signer": "{{ .Values.chains.artifacts.pipelinerun.signer }}", + "artifacts.pipelinerun.enable-deep-inspection": "{{ .Values.chains.artifacts.pipelinerun.enableDeepInspection }}", + "artifacts.oci.format": "{{ .Values.chains.artifacts.oci.format }}", + "artifacts.oci.storage": "{{ .Values.chains.artifacts.oci.storage }}", + "artifacts.oci.signer": "{{ .Values.chains.artifacts.oci.signer }}", + "transparency.enabled": "{{ .Values.chains.transparency.enabled }}", + "transparency.url": "https://rekor-server-trusted-artifact-signer.{{ .Values.global.hubClusterDomain }}", + "signers.x509.fulcio.enabled": "{{ .Values.chains.signers.x509.fulcio.enabled }}", + "signers.x509.fulcio.address": "https://fulcio-server-trusted-artifact-signer.{{ .Values.global.hubClusterDomain }}", + "signers.x509.fulcio.issuer": "https://spire-spiffe-oidc-discovery-provider.{{ .Values.global.hubClusterDomain }}", + "signers.x509.fulcio.provider": "{{ .Values.chains.signers.x509.fulcio.provider }}" + {{- if .Values.chains.signers.x509.tuf.enabled }}, + "signers.x509.tuf.mirror.url": "https://tuf-trusted-artifact-signer.{{ .Values.global.hubClusterDomain }}" + {{- end }} + } + } + }' + echo "TektonConfig patched successfully." + oc get tektonconfig config -o jsonpath='{.spec.chain}' | python3 -m json.tool +{{- end }} diff --git a/charts/tekton-chains/values.yaml b/charts/tekton-chains/values.yaml new file mode 100644 index 00000000..a32d4e35 --- /dev/null +++ b/charts/tekton-chains/values.yaml @@ -0,0 +1,34 @@ +# Tekton Chains Configuration for ZTVP +# Configures the TektonConfig CR to enable Tekton Chains with RHTAS keyless signing + +global: + hubClusterDomain: apps.example.com + +chains: + enabled: true + + artifacts: + taskrun: + format: in-toto + storage: oci + signer: x509 + pipelinerun: + format: in-toto + storage: oci + signer: x509 + enableDeepInspection: true + oci: + format: simplesigning + storage: oci + signer: x509 + + transparency: + enabled: true + + signers: + x509: + fulcio: + enabled: true + provider: spiffe + tuf: + enabled: true diff --git a/docs/SYNC-WAVE-INVENTORY.md b/docs/SYNC-WAVE-INVENTORY.md index fa7a57c1..e2a47083 100644 --- a/docs/SYNC-WAVE-INVENTORY.md +++ b/docs/SYNC-WAVE-INVENTORY.md @@ -70,6 +70,8 @@ Every sync-wave in the repository, in order. **App** = hub-level Argo CD Applica | 46 | └ acs-central | chart | console-link | | 46 | └ acs-secured-cluster | chart | secured-cluster-cr | | 46 | └ rhtas-operator | chart | securesign | +| 47 | tekton-chains | **App** | Tekton Chains config (RHTAS keyless signing) | +| 47 | └ tekton-chains | chart | tektonconfig-chains (TektonConfig CR) | | 48 | supply-chain | **App** | | | 48+0 | └ supply-chain | chart | registry-image-namespace (Namespace, RBAC), pipeline-sa, tasks (incl. restart-qtodo), secrets (quay-pass, rhtpa-pass), quay-user, rhtas/rhtpa-config, pipeline-qtodo-restarter (Role+RoleBinding in qtodo ns) | | 48+1 | └ supply-chain | chart (hook) | enable-registry-default-route (Sync hook Job) | @@ -112,6 +114,7 @@ Every sync-wave in the repository, in order. **App** = hub-level Argo CD Applica | trusted-profile-analyzer | 10 | 41 | Chart resources (OBC, DB, etc.) | | acs-secured-cluster | 15 | 46 | — | | trusted-artifact-signer | 15 | 46 | Deploy after dependencies | +| tekton-chains | — | 47 | After RHTAS, before supply-chain (newly added) | | supply-chain | — | 48 | After RHTAS/ACS, before chart templates (newly added) | | acs-policies | 20 | 51 | After ACS Central + Secured Cluster | @@ -209,6 +212,12 @@ Charts marked **(external)** have been externalized to standalone repositories m | --- | ---: | ---: | | securesign.yaml | 15 | 46 | +### tekton-chains (`charts/tekton-chains/templates/`) — App wave: 47 + +| Resource | Old | Current | +| --- | ---: | ---: | +| tektonconfig-chains.yaml | — | 47 | + ### rhtpa-operator (`charts/rhtpa-operator/templates/`) — App wave: 41 | Resource | Old | Current | diff --git a/scripts/features/features.yaml b/scripts/features/features.yaml index ee35f2cf..49ca349a 100644 --- a/scripts/features/features.yaml +++ b/scripts/features/features.yaml @@ -22,9 +22,13 @@ features: description: "OpenShift Pipelines" depends_on: [] + tekton-chains: + description: "Tekton Chains with RHTAS keyless signing via SPIFFE" + depends_on: [pipelines, rhtas] + supply-chain: description: "Full secure supply chain pipeline" - depends_on: [pipelines, rhtas, rhtpa, storage] + depends_on: [tekton-chains, rhtpa, storage] registry_option_required: true org: ztvp image_name: qtodo diff --git a/scripts/features/quay.yaml b/scripts/features/quay.yaml index bdb44f15..83abd6e9 100644 --- a/scripts/features/quay.yaml +++ b/scripts/features/quay.yaml @@ -25,3 +25,8 @@ clusterGroup: chartVersion: 0.1.* annotations: argocd.argoproj.io/sync-wave: "41" + overrides: + - name: job.image + value: "registry.redhat.io/openshift4/ose-cli:latest" + - name: job.resources.limits.memory + value: "512Mi" diff --git a/scripts/features/registry/option-1-quay.yaml b/scripts/features/registry/option-1-quay.yaml index ef499c06..487be3a8 100644 --- a/scripts/features/registry/option-1-quay.yaml +++ b/scripts/features/registry/option-1-quay.yaml @@ -41,6 +41,8 @@ clusterGroup: overrides: - name: job.image value: "registry.redhat.io/openshift4/ose-cli:latest" + - name: job.resources.limits.memory + value: "512Mi" merge_into_applications: supply-chain: diff --git a/scripts/features/tekton-chains.yaml b/scripts/features/tekton-chains.yaml new file mode 100644 index 00000000..5d1160cf --- /dev/null +++ b/scripts/features/tekton-chains.yaml @@ -0,0 +1,11 @@ +# Tekton Chains for supply chain security with RHTAS keyless signing +# Depends on: pipelines (OpenShift Pipelines operator), rhtas (RHTAS for Fulcio/Rekor/TUF) +# Uses a PostSync Job to patch the operator-managed TektonConfig CR +clusterGroup: + applications: + tekton-chains: + name: tekton-chains + project: hub + path: charts/tekton-chains + annotations: + argocd.argoproj.io/sync-wave: "47" diff --git a/scripts/gen-feature-variants.md b/scripts/gen-feature-variants.md index d084a79a..fe9235e9 100644 --- a/scripts/gen-feature-variants.md +++ b/scripts/gen-feature-variants.md @@ -48,6 +48,9 @@ python3 scripts/gen-feature-variants.py --features rhtpa # Enable multiple features python3 scripts/gen-feature-variants.py --features rhtpa,rhtas +# Enable Tekton Chains (auto-resolves: pipelines -> rhtas -> tekton-chains) +python3 scripts/gen-feature-variants.py --features tekton-chains + # Full supply chain: pick a registry option (1, 2, or 3) python3 scripts/gen-feature-variants.py --features supply-chain --registry-option 1 diff --git a/values-hub.yaml b/values-hub.yaml index dae08bf8..8b0a3360 100644 --- a/values-hub.yaml +++ b/values-hub.yaml @@ -401,6 +401,11 @@ clusterGroup: # chartVersion: 0.1.* # annotations: # argocd.argoproj.io/sync-wave: "41" # Deploy after NooBaa storage backend + # overrides: + # - name: job.image + # value: "registry.redhat.io/openshift4/ose-cli:latest" + # - name: job.resources.limits.memory + # value: "512Mi" # RHTAS with SPIFFE Integration # COMMENTED OUT: Uncomment to enable RHTAS with SPIFFE and Email issuers # Depends on: Vault, SPIRE, Keycloak (for Email OIDC issuer if used) @@ -546,6 +551,17 @@ clusterGroup: # before the supply-chain pipeline runs (avoids ImagePullBackOff on first install) # - name: app.seedImage.enabled # value: "true" + # Tekton Chains - Configures Tekton Chains for supply chain security + # Requires: OpenShift Pipelines operator (openshift-pipelines subscription) + # Requires: RHTAS (trusted-artifact-signer) for keyless signing via SPIFFE + # Uses a PostSync Job to patch the operator-managed TektonConfig CR + # tekton-chains: + # name: tekton-chains + # project: hub + # path: charts/tekton-chains + # annotations: + # argocd.argoproj.io/sync-wave: "47" + # # Secure Supply Chain - Uncomment to enable (required for Option 1, 2, or 3 registry flows in docs) # supply-chain: # name: supply-chain