diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e2888580..d8c7c3c8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,9 +1,11 @@ name: Lint Charts on: - pull_request: - paths: - - "charts/**" + workflow_dispatch: + #pull_request: + # paths: + # - "charts/**" + # - ".github/**" jobs: check-metadata: @@ -57,8 +59,34 @@ jobs: - name: Run chart-testing (lint) run: ct lint --config ct.yaml - #- name: Create KIND Cluster - # uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0 + - name: Create KinD Cluster + uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0 + with: + config: ./kind/config.yaml + + - name: Install OpenShift CLI + run: | + curl -L https://mirror.openshift.com/pub/openshift-v4/clients/oc/latest/linux/oc.tar.gz | tar xvz + sudo mv oc /usr/local/bin/ + oc version + + - name: Configure KinD + run: | + kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml + kubectl apply -f ./kind/servicemonitor-crd.yaml + kubectl create ns fulcio-system + kubectl create ns rekor-system + kubectl -n fulcio-system create secret generic fulcio-secret-rh --from-file=private=./kind/testing-only-cert-key/file_ca_key.pem --from-file=public=./kind/testing-only-cert-key/file_ca_pub.pem --from-file=cert=./kind/testing-only-cert-key/fulcio-root.pem --from-literal=password=secure --dry-run=client -o yaml | oc apply -f- + kubectl -n rekor-system create secret generic rekor-private-key --from-file=private=./kind/testing-only-cert-key/rekor_key.pem --dry-run=client -o yaml | oc apply -f- + kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=90s + shell: bash + + - name: Run chart-testing (install) + run: ct install --helm-extra-args "--wait --wait-for-jobs" --config ct-install.yaml + + - name: Helm test (install) + run: | + OPENSHIFT_APPS_SUBDOMAIN=localhost envsubst < ./charts/trusted-artifact-signer/ci/ci-values.yaml | helm upgrade -i trusted-artifact-signer --debug ./charts/trusted-artifact-signer --wait --wait-for-jobs -n trusted-artifact-signer --create-namespace --values - - #- name: Run chart-testing (install) - # run: ct install --config ct-install.yaml + helm test -n trusted-artifact-signer trusted-artifact-signer + # tests are in charts/trusted-artifact-signer/templates/tests diff --git a/.gitignore b/.gitignore index 2ea883df..ec5ee476 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,5 @@ Chart.lock *.swp keys-cert -*.pem ./keys-cert/*.pem **ADMIN** diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 00000000..607a600a --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,8 @@ +[allowlist] + description = "Global Allowlist" + + # Ignore based on any subset of the file path + paths = [ + # Ignore all example certs + '''\/testing-only-cert-key\/*\.pem$''', + ] diff --git a/README.md b/README.md index 9b943eea..4fb65651 100644 --- a/README.md +++ b/README.md @@ -14,3 +14,41 @@ Information on how to install Sigstore components on OpenShift can be found in t ## Scaffolding Chart More information can be found by inspecting the [trusted-artifact-signer chart](charts/trusted-artifact-signer). + +## Contributing + +Install the [pre-commit](https://pre-commit.com/) package and run `pre-commit run --all-files` before pushing changes, or `pre-commit install` to automatically run the pre-commit hooks with every `git commit`. If it fails, +run the `git commit` command again. It's likely the pre-commit hook fixed the issue and you have to bring in the new changes. + +### Testing + +To set up a `kind` cluster and deploy the charts, run the following from the root of this repository + +```bash +./kind/kind-up-test.sh + +kubectl wait --namespace ingress-nginx \ + --for=condition=ready pod \ + --selector=app.kubernetes.io/component=controller \ + --timeout=90s + +OPENSHIFT_APPS_SUBDOMAIN=localhost envsubst < ./examples/values-kind-sigstore.yaml | helm upgrade -i trusted-artifact-signer --debug ./charts/trusted-artifact-signer --wait --wait-for-jobs -n sigstore --create-namespace --values - + +helm test -n sigstore trusted-artifact-signer +# tests are in charts/trusted-artifact-signer/templates/tests +``` + +This test setup is to verify that all deployments are healthy and all jobs complete. However, this does not create a working environment to sign artifacts. + +To uninstall helm chart: + +```bash +helm uninstall trusted-artifact-signer -n sigstore +``` + +To cleanup the test kind cluster, run: + +```bash +sudo kind delete cluster +``` + diff --git a/charts/trusted-artifact-signer/Chart.yaml b/charts/trusted-artifact-signer/Chart.yaml index 5386def4..96426a80 100644 --- a/charts/trusted-artifact-signer/Chart.yaml +++ b/charts/trusted-artifact-signer/Chart.yaml @@ -33,4 +33,4 @@ sources: # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.4 +version: 0.1.5 diff --git a/charts/trusted-artifact-signer/README.md b/charts/trusted-artifact-signer/README.md index 8d9964cd..023700b9 100644 --- a/charts/trusted-artifact-signer/README.md +++ b/charts/trusted-artifact-signer/README.md @@ -3,7 +3,7 @@ A Helm chart for deploying Sigstore scaffold chart that is opinionated for OpenShift -![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) +![Version: 0.1.5](https://img.shields.io/badge/Version-0.1.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ## Overview @@ -128,7 +128,7 @@ Kubernetes: `>= 1.19.0-0` | rbac.clusterrole | clusterrole to be added to sigstore component serviceaccounts. | string | `"system:openshift:scc:anyuid"` | | scaffold.copySecretJob.backoffLimit | | int | `1000` | | scaffold.copySecretJob.enabled | | bool | `true` | -| scaffold.copySecretJob.imagePullPolicy | | string | `"Always"` | +| scaffold.copySecretJob.imagePullPolicy | | string | `"IfNotPresent"` | | scaffold.copySecretJob.name | | string | `"copy-secrets-job"` | | scaffold.copySecretJob.registry | | string | `"quay.io"` | | scaffold.copySecretJob.repository | | string | `"sallyom/copy-secrets"` | @@ -139,8 +139,8 @@ Kubernetes: `>= 1.19.0-0` | scaffold.ctlog.createctconfig.enabled | | bool | `true` | | scaffold.ctlog.createctconfig.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.ctlog.createctconfig.image.registry | | string | `"quay.io"` | -| scaffold.ctlog.createctconfig.image.repository | | string | `"securesign/createctconfig"` | -| scaffold.ctlog.createctconfig.image.version | | string | `"v0.6.4"` | +| scaffold.ctlog.createctconfig.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/createctconfig"` | +| scaffold.ctlog.createctconfig.image.version | | string | `"build-96ab3-1696275762"` | | scaffold.ctlog.createctconfig.initContainerImage.curl.imagePullPolicy | | string | `"IfNotPresent"` | | scaffold.ctlog.createctconfig.initContainerImage.curl.registry | | string | `"registry.access.redhat.com"` | | scaffold.ctlog.createctconfig.initContainerImage.curl.repository | | string | `"ubi9/ubi-minimal"` | @@ -149,8 +149,8 @@ Kubernetes: `>= 1.19.0-0` | scaffold.ctlog.createtree.fullnameOverride | | string | `"ctlog-createtree"` | | scaffold.ctlog.createtree.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.ctlog.createtree.image.registry | | string | `"quay.io"` | -| scaffold.ctlog.createtree.image.repository | | string | `"securesign/createtree"` | -| scaffold.ctlog.createtree.image.version | | string | `"v0.6.4"` | +| scaffold.ctlog.createtree.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/createtree"` | +| scaffold.ctlog.createtree.image.version | | string | `"build-1a625-1696276030"` | | scaffold.ctlog.enabled | | bool | `true` | | scaffold.ctlog.forceNamespace | | string | `"ctlog-system"` | | scaffold.ctlog.fullnameOverride | | string | `"ctlog"` | @@ -158,14 +158,14 @@ Kubernetes: `>= 1.19.0-0` | scaffold.ctlog.namespace.name | | string | `"ctlog-system"` | | scaffold.ctlog.server.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.ctlog.server.image.registry | | string | `"quay.io"` | -| scaffold.ctlog.server.image.repository | | string | `"securesign/ct_server"` | -| scaffold.ctlog.server.image.version | | string | `"v0.6.4"` | +| scaffold.ctlog.server.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/ct-server"` | +| scaffold.ctlog.server.image.version | | string | `"build-68eb0-1696273861"` | | scaffold.fulcio.createcerts.enabled | | bool | `false` | | scaffold.fulcio.createcerts.fullnameOverride | | string | `"fulcio-createcerts"` | | scaffold.fulcio.createcerts.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.fulcio.createcerts.image.registry | | string | `"quay.io"` | -| scaffold.fulcio.createcerts.image.repository | | string | `"securesign/createcerts"` | -| scaffold.fulcio.createcerts.image.version | | string | `"v0.6.4"` | +| scaffold.fulcio.createcerts.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/createcerts"` | +| scaffold.fulcio.createcerts.image.version | | string | `"cfd61c13698b4e73e9c389dafc082134d0ab80a5"` | | scaffold.fulcio.ctlog.createctconfig.logPrefix | | string | `"sigstorescaffolding"` | | scaffold.fulcio.ctlog.enabled | | bool | `false` | | scaffold.fulcio.enabled | | bool | `true` | @@ -175,8 +175,8 @@ Kubernetes: `>= 1.19.0-0` | scaffold.fulcio.server.fullnameOverride | | string | `"fulcio-server"` | | scaffold.fulcio.server.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.fulcio.server.image.registry | | string | `"quay.io"` | -| scaffold.fulcio.server.image.repository | | string | `"securesign/fulcio"` | -| scaffold.fulcio.server.image.version | | string | `"v1.4.0"` | +| scaffold.fulcio.server.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/fulcio"` | +| scaffold.fulcio.server.image.version | | string | `"1187db2ca9927ceabe3a2a3fedb67d4a3f8ef323"` | | scaffold.fulcio.server.ingress.http.annotations."route.openshift.io/termination" | | string | `"edge"` | | scaffold.fulcio.server.ingress.http.className | | string | `""` | | scaffold.fulcio.server.ingress.http.enabled | | bool | `true` | @@ -185,12 +185,12 @@ Kubernetes: `>= 1.19.0-0` | scaffold.fulcio.server.secret | | string | `"fulcio-secret-rh"` | | scaffold.rekor.backfillredis.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.rekor.backfillredis.image.registry | | string | `"quay.io"` | -| scaffold.rekor.backfillredis.image.repository | | string | `"securesign/backfill-redis"` | -| scaffold.rekor.backfillredis.image.version | | string | `"v1.2.2"` | +| scaffold.rekor.backfillredis.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/backfill-redis"` | +| scaffold.rekor.backfillredis.image.version | | string | `"ce862e267bee178fbf16ab7d181ff8f21246e346"` | | scaffold.rekor.createtree.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.rekor.createtree.image.registry | | string | `"quay.io"` | -| scaffold.rekor.createtree.image.repository | | string | `"securesign/createtree"` | -| scaffold.rekor.createtree.image.version | | string | `"v0.6.4"` | +| scaffold.rekor.createtree.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/createtree"` | +| scaffold.rekor.createtree.image.version | | string | `"build-1a625-1696276030"` | | scaffold.rekor.enabled | | bool | `true` | | scaffold.rekor.forceNamespace | | string | `"rekor-system"` | | scaffold.rekor.fullnameOverride | | string | `"rekor"` | @@ -214,8 +214,8 @@ Kubernetes: `>= 1.19.0-0` | scaffold.rekor.trillian.enabled | | bool | `false` | | scaffold.trillian.createdb.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.trillian.createdb.image.registry | | string | `"quay.io"` | -| scaffold.trillian.createdb.image.repository | | string | `"securesign/createdb"` | -| scaffold.trillian.createdb.image.version | | string | `"v0.6.4"` | +| scaffold.trillian.createdb.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/createdb"` | +| scaffold.trillian.createdb.image.version | | string | `"build-b43c0-1696275867"` | | scaffold.trillian.enabled | | bool | `true` | | scaffold.trillian.forceNamespace | | string | `"trillian-system"` | | scaffold.trillian.fullnameOverride | | string | `"trillian"` | @@ -224,31 +224,31 @@ Kubernetes: `>= 1.19.0-0` | scaffold.trillian.initContainerImage.curl.repository | | string | `"ubi9/ubi-minimal"` | | scaffold.trillian.initContainerImage.curl.version | | string | `"latest"` | | scaffold.trillian.initContainerImage.netcat.registry | | string | `"quay.io"` | -| scaffold.trillian.initContainerImage.netcat.repository | | string | `"securesign/netcat"` | -| scaffold.trillian.initContainerImage.netcat.version | | string | `"v1.0.0"` | +| scaffold.trillian.initContainerImage.netcat.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/trillian-netcat"` | +| scaffold.trillian.initContainerImage.netcat.version | | string | `"build-3c019-1696503519"` | | scaffold.trillian.logServer.fullnameOverride | | string | `"trillian-logserver"` | | scaffold.trillian.logServer.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.trillian.logServer.image.registry | | string | `"quay.io"` | -| scaffold.trillian.logServer.image.repository | | string | `"securesign/trillian_log_server"` | -| scaffold.trillian.logServer.image.version | | string | `"v1.2.2"` | +| scaffold.trillian.logServer.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/trillian-logserver"` | +| scaffold.trillian.logServer.image.version | | string | `"build-58a79-1696502872"` | | scaffold.trillian.logServer.name | | string | `"trillian-logserver"` | | scaffold.trillian.logServer.portHTTP | | int | `8090` | | scaffold.trillian.logServer.portRPC | | int | `8091` | | scaffold.trillian.logSigner.fullnameOverride | | string | `"trillian-logsigner"` | | scaffold.trillian.logSigner.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.trillian.logSigner.image.registry | | string | `"quay.io"` | -| scaffold.trillian.logSigner.image.repository | | string | `"securesign/trillian_log_signer"` | -| scaffold.trillian.logSigner.image.version | | string | `"v1.2.2"` | +| scaffold.trillian.logSigner.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/trillian-logsigner"` | +| scaffold.trillian.logSigner.image.version | | string | `"build-38813-1696586021"` | | scaffold.trillian.logSigner.name | | string | `"trillian-logsigner"` | | scaffold.trillian.mysql.args | | list | `[]` | | scaffold.trillian.mysql.fullnameOverride | | string | `"trillian-mysql"` | | scaffold.trillian.mysql.gcp.scaffoldSQLProxy.registry | | string | `"quay.io"` | -| scaffold.trillian.mysql.gcp.scaffoldSQLProxy.repository | | string | `"securesign/cloudsqlproxy"` | -| scaffold.trillian.mysql.gcp.scaffoldSQLProxy.version | | string | `"v0.6.4"` | +| scaffold.trillian.mysql.gcp.scaffoldSQLProxy.repository | | string | `"docker pull quay.io/redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/cloudsqlproxy"` | +| scaffold.trillian.mysql.gcp.scaffoldSQLProxy.version | | string | `"build-b9416-1696274309"` | | scaffold.trillian.mysql.image.pullPolicy | | string | `"IfNotPresent"` | | scaffold.trillian.mysql.image.registry | | string | `"quay.io"` | -| scaffold.trillian.mysql.image.repository | | string | `"securesign/trillian-db"` | -| scaffold.trillian.mysql.image.version | | string | `"v1.5.2"` | +| scaffold.trillian.mysql.image.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/trillian-database"` | +| scaffold.trillian.mysql.image.version | | string | `"build-b3117-1696585835"` | | scaffold.trillian.mysql.livenessProbe.exec.command[0] | | string | `"mysqladmin"` | | scaffold.trillian.mysql.livenessProbe.exec.command[1] | | string | `"ping"` | | scaffold.trillian.mysql.livenessProbe.exec.command[2] | | string | `"-h"` | @@ -281,8 +281,8 @@ Kubernetes: `>= 1.19.0-0` | scaffold.tsa.namespace.name | | string | `"tsa-system"` | | scaffold.tsa.server.fullnameOverride | | string | `"tsa-server"` | | scaffold.tuf.deployment.registry | | string | `"quay.io"` | -| scaffold.tuf.deployment.repository | | string | `"securesign/tuf/server"` | -| scaffold.tuf.deployment.version | | string | `"latest"` | +| scaffold.tuf.deployment.repository | | string | `"redhat-user-workloads/rhtas-tenant/rhtas-stack-1-0-beta/tuf-server"` | +| scaffold.tuf.deployment.version | | string | `"cfd61c13698b4e73e9c389dafc082134d0ab80a5"` | | scaffold.tuf.enabled | | bool | `true` | | scaffold.tuf.forceNamespace | | string | `"tuf-system"` | | scaffold.tuf.fullnameOverride | | string | `"tuf"` | @@ -293,7 +293,7 @@ Kubernetes: `>= 1.19.0-0` | scaffold.tuf.namespace.create | | bool | `false` | | scaffold.tuf.namespace.name | | string | `"tuf-system"` | | scaffold.tuf.secrets.ctlog.name | | string | `"ctlog-public-key"` | -| scaffold.tuf.secrets.ctlog.path | | string | `"ctlog-pubkey"` | +| scaffold.tuf.secrets.ctlog.path | | string | `"ctfe.pub"` | | scaffold.tuf.secrets.fulcio.name | | string | `"fulcio-secret-rh"` | | scaffold.tuf.secrets.fulcio.path | | string | `"fulcio-cert"` | | scaffold.tuf.secrets.rekor.name | | string | `"rekor-public-key"` | diff --git a/charts/trusted-artifact-signer/ci/ci-values.yaml b/charts/trusted-artifact-signer/ci/ci-values.yaml new file mode 100644 index 00000000..2ab41719 --- /dev/null +++ b/charts/trusted-artifact-signer/ci/ci-values.yaml @@ -0,0 +1,49 @@ +# With this example, it is expected that there is a secret with the fulcio root & signing keys +# named 'fulcio-secret-rh' in namespace 'fulcio-system' and a secret 'rekor-private-key' +# with rekor signing keys in the 'rekor-system' namespace. +# secret names must match secret names in scaffold.tuf, that default to +# 'fulcio-secret-rh' and 'rekor-private-key' +# For root & key requirements, see ../requirements-keys-certs.md +# Note: User must substitute for localhost below. +--- +configs: + cosign: + appsSubdomain: localhost + fulcio: + create: false + rekor: + create: false + +# github.com/sigstore/helm-charts/charts +scaffold: + fulcio: + clusterMonitoring: + enabled: false + server: + ingress: + http: + hosts: + - host: fulcio.localhost + path: / + config: + contents: + OIDCIssuers: + # https://../auth/realms/sigstore + ? https://keycloak-keycloak-system.apps.open-svc-sts.k1wl.p1.openshiftapps.com/auth/realms/sigstore + : IssuerURL: https://keycloak-keycloak-system.apps.open-svc-sts.k1wl.p1.openshiftapps.com/auth/realms/sigstore + ClientID: sigstore + Type: email + rekor: + clusterMonitoring: + enabled: false + server: + ingress: + hosts: + - host: rekor.localhost + path: / + tuf: + ingress: + http: + hosts: + - host: tuf.localhost + path: / \ No newline at end of file diff --git a/charts/trusted-artifact-signer/templates/_helpers.tpl b/charts/trusted-artifact-signer/templates/_helpers.tpl index fe146a48..4038d9db 100644 --- a/charts/trusted-artifact-signer/templates/_helpers.tpl +++ b/charts/trusted-artifact-signer/templates/_helpers.tpl @@ -1,7 +1,7 @@ {{/* Expand the name of the chart. */}} -{{- define "sigstore-openshift.name" -}} +{{- define "trusted-artifact-signer.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} @@ -10,7 +10,7 @@ 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 "sigstore-openshift.fullname" -}} +{{- define "trusted-artifact-signer.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} @@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name. {{/* Create chart name and version as used by the chart label. */}} -{{- define "sigstore-openshift.chart" -}} +{{- define "trusted-artifact-signer.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} -{{- define "sigstore-openshift.labels" -}} -helm.sh/chart: {{ include "sigstore-openshift.chart" . }} -{{ include "sigstore-openshift.selectorLabels" . }} +{{- define "trusted-artifact-signer.labels" -}} +helm.sh/chart: {{ include "trusted-artifact-signer.chart" . }} +{{ include "trusted-artifact-signer.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} @@ -45,17 +45,17 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} {{/* Selector labels */}} -{{- define "sigstore-openshift.selectorLabels" -}} -app.kubernetes.io/name: {{ include "sigstore-openshift.name" . }} +{{- define "trusted-artifact-signer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "trusted-artifact-signer.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{/* Create the name of the service account to use */}} -{{- define "sigstore-openshift.serviceAccountName" -}} +{{- define "trusted-artifact-signer.serviceAccountName" -}} {{- if .Values.serviceAccount.create }} -{{- default (include "sigstore-openshift.fullname" .) .Values.serviceAccount.name }} +{{- default (include "trusted-artifact-signer.fullname" .) .Values.serviceAccount.name }} {{- else }} {{- default "default" .Values.serviceAccount.name }} {{- end }} diff --git a/charts/trusted-artifact-signer/templates/cosign-deployment.yaml b/charts/trusted-artifact-signer/templates/cosign-deployment.yaml index 7a951064..d6fa0c79 100644 --- a/charts/trusted-artifact-signer/templates/cosign-deployment.yaml +++ b/charts/trusted-artifact-signer/templates/cosign-deployment.yaml @@ -12,29 +12,30 @@ spec: labels: app: {{ .Values.configs.cosign.name }} spec: + securityContext: + runAsNonRoot: true + runAsUser: 65533 + {{- if $.Values.configs.cosign.rolebindings }} + serviceAccountName: {{ index .Values.configs.cosign.rolebindings 0 }} + {{- end }} containers: - name: {{ .Values.configs.cosign.name }} image: "{{ .Values.configs.cosign.image.registry }}/{{ .Values.configs.cosign.image.repository }}:{{ .Values.configs.cosign.image.version }}" env: - name: OPENSHIFT_APPS_SUBDOMAIN value: {{ .Values.configs.cosign.appsSubdomain }} - - name: KEYCLOAK_REALM + - name: OIDC_AUTHENTICATION_REALM value: "sigstore" - name: FULCIO_URL value: "https://fulcio.$(OPENSHIFT_APPS_SUBDOMAIN)" - - name: KEYCLOAK_URL - value: "https://keycloak-keycloak-system.$(OPENSHIFT_APPS_SUBDOMAIN)" + - name: OIDC_ISSUER_URL + value: "https://keycloak-keycloak-system.$(OPENSHIFT_APPS_SUBDOMAIN)/auth/realms/$(OIDC_AUTHENTICATION_REALM)" - name: REKOR_URL value: "https://rekor.$(OPENSHIFT_APPS_SUBDOMAIN)" - name: TUF_URL value: "https://tuf.$(OPENSHIFT_APPS_SUBDOMAIN)" - - name: KEYCLOAK_OIDC_ISSUER - value: "$KEYCLOAK_URL/auth/realms/$(KEYCLOAK_REALM)" securityContext: allowPrivilegeEscalation: false - runAsNonRoot: true capabilities: drop: - - ALL - seccompProfile: - type: RuntimeDefault \ No newline at end of file + - ALL \ No newline at end of file diff --git a/charts/trusted-artifact-signer/templates/cosign-sa.yaml b/charts/trusted-artifact-signer/templates/cosign-sa.yaml new file mode 100644 index 00000000..894f7a7a --- /dev/null +++ b/charts/trusted-artifact-signer/templates/cosign-sa.yaml @@ -0,0 +1,8 @@ +{{- if $.Values.configs.cosign.rolebindings }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Values.configs.cosign.namespace }} + name: {{ index .Values.configs.cosign.rolebindings 0 }} +{{- end }} diff --git a/charts/trusted-artifact-signer/templates/tests/test-connection.yaml b/charts/trusted-artifact-signer/templates/tests/test-connection.yaml new file mode 100644 index 00000000..7c8f511c --- /dev/null +++ b/charts/trusted-artifact-signer/templates/tests/test-connection.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: trusted-artifact-signer-test-connection + labels: + app.kubernetes.io/component: trusted-artifact-signer + annotations: + helm.sh/hook: test +spec: + containers: + - name: curl + image: registry.access.redhat.com/ubi9/ubi-minimal:latest + command: ["/bin/sh", "-c"] + args: + - | + curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80 + curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80/targets/ + curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80/targets/ctfe.pub + curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80/targets/fulcio-cert + curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80/targets/rekor-pubkey + restartPolicy: Never diff --git a/charts/trusted-artifact-signer/values.yaml b/charts/trusted-artifact-signer/values.yaml index 84de8c15..f0c986f4 100644 --- a/charts/trusted-artifact-signer/values.yaml +++ b/charts/trusted-artifact-signer/values.yaml @@ -124,6 +124,7 @@ configs: # -- Image containing the cosign binary as well as environment variables with the base domain injected. image: registry: quay.io + # TODO: update image repository: securesign/cosign version: v2.1.1 pullPolicy: IfNotPresent @@ -225,6 +226,7 @@ scaffold: fullnameOverride: rekor-server image: registry: quay.io + # TODO: update image repository: securesign/rekor-server version: v1.2.2 pullPolicy: IfNotPresent diff --git a/examples/values-kind-sigstore.yaml b/examples/values-kind-sigstore.yaml new file mode 100644 index 00000000..ff72803b --- /dev/null +++ b/examples/values-kind-sigstore.yaml @@ -0,0 +1,49 @@ +# With this example, it is expected that there is a secret with the fulcio root & signing keys +# named 'fulcio-secret-rh' in namespace 'fulcio-system' and a secret 'rekor-private-key' +# with rekor signing keys in the 'rekor-system' namespace. +# secret names must match secret names in scaffold.tuf, that default to +# 'fulcio-secret-rh' and 'rekor-private-key' +# For root & key requirements, see ../requirements-keys-certs.md +# Note: User must substitute for $OPENSHIFT_APPS_SUBDOMAIN below. +--- +configs: + cosign: + appsSubdomain: $OPENSHIFT_APPS_SUBDOMAIN + fulcio: + create: false + rekor: + create: false + +# github.com/sigstore/helm-charts/charts +scaffold: + fulcio: + clusterMonitoring: + enabled: false + server: + ingress: + http: + hosts: + - host: fulcio.$OPENSHIFT_APPS_SUBDOMAIN + path: / + config: + contents: + OIDCIssuers: + # https://../auth/realms/sigstore + ? https://keycloak-keycloak-system.apps.open-svc-sts.k1wl.p1.openshiftapps.com/auth/realms/sigstore + : IssuerURL: https://keycloak-keycloak-system.apps.open-svc-sts.k1wl.p1.openshiftapps.com/auth/realms/sigstore + ClientID: sigstore + Type: email + rekor: + clusterMonitoring: + enabled: false + server: + ingress: + hosts: + - host: rekor.$OPENSHIFT_APPS_SUBDOMAIN + path: / + tuf: + ingress: + http: + hosts: + - host: tuf.$OPENSHIFT_APPS_SUBDOMAIN + path: / \ No newline at end of file diff --git a/kind/config.yaml b/kind/config.yaml new file mode 100644 index 00000000..d4c70073 --- /dev/null +++ b/kind/config.yaml @@ -0,0 +1,17 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + - containerPort: 80 + hostPort: 80 + protocol: TCP + - containerPort: 443 + hostPort: 443 + protocol: TCP diff --git a/kind/kind-up-test.sh b/kind/kind-up-test.sh new file mode 100755 index 00000000..1022fa82 --- /dev/null +++ b/kind/kind-up-test.sh @@ -0,0 +1,58 @@ +# run this from root of repository + +# spin up kind cluster +cat < /tmp/config +sudo chown $USER:$USER /tmp/config +if [[ -d ~/.kube ]] && [[ -f ~/.kube/config ]] +then + export KUBECONFIG=~/.kube/config:/tmp/config + kubectl config view --flatten > merged-config.yaml + mv merged-config.yaml ~/.kube/config +else + mv /tmp/config ~/.kube/config +fi + +kubectl config use-context kind-kind + +# install ingress-nginx +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml + +# add servicemonitor crd +kubectl apply -f ./kind/servicemonitor-crd.yaml + +#kubectl wait --namespace ingress-nginx \ +# --for=condition=ready pod \ +# --selector=app.kubernetes.io/component=controller \ +# --timeout=90s +# +# TODO: add a wait for ingress to be ready with test.yaml & curl +#sleep 20 + +oc create ns fulcio-system +oc create ns rekor-system +oc -n fulcio-system create secret generic fulcio-secret-rh --from-file=private=./kind/testing-only-cert-key/file_ca_key.pem --from-file=public=./kind/testing-only-cert-key/file_ca_pub.pem --from-file=cert=./kind/testing-only-cert-key/fulcio-root.pem --from-literal=password=secure --dry-run=client -o yaml | oc apply -f- + +oc -n rekor-system create secret generic rekor-private-key --from-file=private=./kind/testing-only-cert-key/rekor_key.pem --dry-run=client -o yaml | oc apply -f- + +# install charts +#OPENSHIFT_APPS_SUBDOMAIN=localhost envsubst < ./examples/values-kind-sigstore.yaml | helm upgrade -i trusted-artifact-signer --debug ./charts/trusted-artifact-signer --wait --wait-for-jobs -n sigstore --create-namespace --values - diff --git a/kind/servicemonitor-crd.yaml b/kind/servicemonitor-crd.yaml new file mode 100644 index 00000000..e8b548ae --- /dev/null +++ b/kind/servicemonitor-crd.yaml @@ -0,0 +1,681 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: servicemonitors.monitoring.coreos.com +spec: + conversion: + strategy: None + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: ServiceMonitor + listKind: ServiceMonitorList + plural: servicemonitors + shortNames: + - smon + singular: servicemonitor + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ServiceMonitor defines monitoring for a set of services. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Specification of desired Service selection for target discovery + by Prometheus. + properties: + endpoints: + description: A list of endpoints allowed as part of this ServiceMonitor. + items: + description: Endpoint defines a scrapeable endpoint serving Prometheus + metrics. + properties: + authorization: + description: Authorization section for this endpoint + properties: + credentials: + description: The secret's key that contains the credentials + of the request + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: + description: Set the authentication type. Defaults to Bearer, + Basic will cause an error + type: string + type: object + basicAuth: + description: 'BasicAuth allow an endpoint to authenticate over + basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' + properties: + password: + description: The secret in the service monitor namespace + that contains the password for authentication. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + username: + description: The secret in the service monitor namespace + that contains the username for authentication. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + bearerTokenFile: + description: File to read bearer token for scraping targets. + type: string + bearerTokenSecret: + description: Secret to mount to read bearer token for scraping + targets. The secret needs to be in the same namespace as the + service monitor and accessible by the Prometheus Operator. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + enableHttp2: + description: Whether to enable HTTP2. + type: boolean + followRedirects: + description: FollowRedirects configures whether scrape requests + follow HTTP 3xx redirects. + type: boolean + honorLabels: + description: HonorLabels chooses the metric's labels on collisions + with target labels. + type: boolean + honorTimestamps: + description: HonorTimestamps controls whether Prometheus respects + the timestamps present in scraped data. + type: boolean + interval: + description: Interval at which metrics should be scraped If + not specified Prometheus' global scrape interval is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + metricRelabelings: + description: MetricRelabelConfigs to apply to samples before + ingestion. + items: + description: 'RelabelConfig allows dynamic rewriting of the + label set, being applied to samples before ingestion. It + defines ``-section of Prometheus + configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + default: replace + description: Action to perform based on regex matching. + Default is 'replace'. uppercase and lowercase actions + require Prometheus >= 2.36. + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex + capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + description: LabelName is a valid Prometheus label name + which may only contain ASCII letters, numbers, as + well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + oauth2: + description: OAuth2 for the URL. Only valid in Prometheus versions + 2.27.0 and newer. + properties: + clientId: + description: The secret or configmap containing the OAuth2 + client id + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: The secret containing the OAuth2 client secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: Parameters to append to the token URL + type: object + scopes: + description: OAuth2 scopes used for the token request + items: + type: string + type: array + tokenUrl: + description: The URL to fetch the token from + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + params: + additionalProperties: + items: + type: string + type: array + description: Optional HTTP URL parameters + type: object + path: + description: HTTP path to scrape for metrics. If empty, Prometheus + uses the default value (e.g. `/metrics`). + type: string + port: + description: Name of the service port this endpoint refers to. + Mutually exclusive with targetPort. + type: string + proxyUrl: + description: ProxyURL eg http://proxyserver:2195 Directs scrapes + to proxy through this endpoint. + type: string + relabelings: + description: 'RelabelConfigs to apply to samples before scraping. + Prometheus Operator automatically adds relabelings for a few + standard Kubernetes fields. The original scrape job''s name + is available via the `__tmp_prometheus_job_name` label. More + info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' + items: + description: 'RelabelConfig allows dynamic rewriting of the + label set, being applied to samples before ingestion. It + defines ``-section of Prometheus + configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' + properties: + action: + default: replace + description: Action to perform based on regex matching. + Default is 'replace'. uppercase and lowercase actions + require Prometheus >= 2.36. + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + type: string + modulus: + description: Modulus to take of the hash of the source + label values. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. Default is '(.*)' + type: string + replacement: + description: Replacement value against which a regex replace + is performed if the regular expression matches. Regex + capture groups are available. Default is '$1' + type: string + separator: + description: Separator placed between concatenated source + label values. default is ';'. + type: string + sourceLabels: + description: The source labels select values from existing + labels. Their content is concatenated using the configured + separator and matched against the configured regular + expression for the replace, keep, and drop actions. + items: + description: LabelName is a valid Prometheus label name + which may only contain ASCII letters, numbers, as + well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: Label to which the resulting value is written + in a replace action. It is mandatory for replace actions. + Regex capture groups are available. + type: string + type: object + type: array + scheme: + description: HTTP scheme to use for scraping. + type: string + scrapeTimeout: + description: Timeout after which the scrape is ended If not + specified, the Prometheus global scrape timeout is used unless + it is less than `Interval` in which the latter is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + targetPort: + anyOf: + - type: integer + - type: string + description: Name or number of the target port of the Pod behind + the Service, the port must be specified with container port + property. Mutually exclusive with port. + x-kubernetes-int-or-string: true + tlsConfig: + description: TLS configuration to use when scraping the endpoint + properties: + ca: + description: Struct containing the CA cert to use for the + targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + caFile: + description: Path to the CA cert in the Prometheus container + to use for the targets. + type: string + cert: + description: Struct containing the client cert file for + the targets. + properties: + configMap: + description: ConfigMap containing data to use for the + targets. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + description: Secret containing data to use for the targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + certFile: + description: Path to the client cert file in the Prometheus + container for the targets. + type: string + insecureSkipVerify: + description: Disable target certificate validation. + type: boolean + keyFile: + description: Path to the client key file in the Prometheus + container for the targets. + type: string + keySecret: + description: Secret containing the client key file for the + targets. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + type: object + type: array + jobLabel: + description: "JobLabel selects the label from the associated Kubernetes + service which will be used as the `job` label for all metrics. \n + For example: If in `ServiceMonitor.spec.jobLabel: foo` and in `Service.metadata.labels.foo: + bar`, then the `job=\"bar\"` label is added to all metrics. \n If + the value of this field is empty or if the label doesn't exist for + the given Service, the `job` label of the metrics defaults to the + name of the Kubernetes Service." + type: string + labelLimit: + description: Per-scrape limit on number of labels that will be accepted + for a sample. Only valid in Prometheus versions 2.27.0 and newer. + format: int64 + type: integer + labelNameLengthLimit: + description: Per-scrape limit on length of labels name that will be + accepted for a sample. Only valid in Prometheus versions 2.27.0 + and newer. + format: int64 + type: integer + labelValueLengthLimit: + description: Per-scrape limit on length of labels value that will + be accepted for a sample. Only valid in Prometheus versions 2.27.0 + and newer. + format: int64 + type: integer + namespaceSelector: + description: Selector to select which namespaces the Kubernetes Endpoints + objects are discovered from. + properties: + any: + description: Boolean describing whether all namespaces are selected + in contrast to a list restricting them. + type: boolean + matchNames: + description: List of namespace names to select from. + items: + type: string + type: array + type: object + podTargetLabels: + description: PodTargetLabels transfers labels on the Kubernetes `Pod` + onto the created metrics. + items: + type: string + type: array + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + selector: + description: Selector to select Endpoints objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that relates the key + and values. + 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. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + 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 + type: object + x-kubernetes-map-type: atomic + targetLabels: + description: TargetLabels transfers labels from the Kubernetes `Service` + onto the created metrics. + items: + type: string + type: array + targetLimit: + description: TargetLimit defines a limit on the number of scraped + targets that will be accepted. + format: int64 + type: integer + required: + - endpoints + - selector + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/kind/testing-only-cert-key/file_ca_key.pem b/kind/testing-only-cert-key/file_ca_key.pem new file mode 100644 index 00000000..9faf9f13 --- /dev/null +++ b/kind/testing-only-cert-key/file_ca_key.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,57052BF0C94F8233 + +iYxyAS5gRrPrdKDdEvzokWkp5z5swdqkxyuGx98gcMHnkJlW+sa53cAqqnLefNXO +y/pROXH0PXhKg+5sMcwJCba8yf5obQOiqWsrH7ERb5SC+OmXvnIxTallp6fRw6W0 +jWRrqUp+QpQxfdKwSrLMYVPQw8e9iVewNZkZxPC0YVI= +-----END EC PRIVATE KEY----- diff --git a/kind/testing-only-cert-key/file_ca_pub.pem b/kind/testing-only-cert-key/file_ca_pub.pem new file mode 100644 index 00000000..485772cb --- /dev/null +++ b/kind/testing-only-cert-key/file_ca_pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+l00SWziQVPM+ubkppU3gSpdJnzd +hDqojvHYY6GRTDTZcFlU24mouB/ARzT1eS6giaFbehlg5QEm6GhfWdbiww== +-----END PUBLIC KEY----- diff --git a/kind/testing-only-cert-key/fulcio-root.pem b/kind/testing-only-cert-key/fulcio-root.pem new file mode 100644 index 00000000..23e9680b --- /dev/null +++ b/kind/testing-only-cert-key/fulcio-root.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICTjCCAfOgAwIBAgIUW9JM5WZNic2pGCTv6jYea2xBprQwCgYIKoZIzj0EAwIw +fDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBU1haW5lMREwDwYDVQQHDAhQb3J0bGFu +ZDEQMA4GA1UECgwHUmVkIEhhdDEUMBIGA1UEAwwLc2lnc3RvcmUuZXoxIjAgBgkq +hkiG9w0BCQEWE3NvbWFsbGV5QHJlZGhhdC5jb20wHhcNMjMwOTI2MTgyNTEwWhcN +MjQwOTI1MTgyNTEwWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFTWFpbmUxETAP +BgNVBAcMCFBvcnRsYW5kMRAwDgYDVQQKDAdSZWQgSGF0MRQwEgYDVQQDDAtzaWdz +dG9yZS5lejEiMCAGCSqGSIb3DQEJARYTc29tYWxsZXlAcmVkaGF0LmNvbTBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABPpdNEls4kFTzPrm5KaVN4EqXSZ83YQ6qI7x +2GOhkUw02XBZVNuJqLgfwEc09XkuoImhW3oZYOUBJuhoX1nW4sOjUzBRMB0GA1Ud +DgQWBBTXTK85svHwwn0vEmkp5+rvF9yL8jAfBgNVHSMEGDAWgBTXTK85svHwwn0v +Emkp5+rvF9yL8jAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQDO +lLxcAuWYU2GqCG2XMaEEIIOX5ns5sf11MY6NdGcBngIhAMvOa1BZ7XYEGHj0G17y +lAqCBO3yklG3WNHoj8Hm4YGZ +-----END CERTIFICATE----- diff --git a/kind/testing-only-cert-key/rekor_key.pem b/kind/testing-only-cert-key/rekor_key.pem new file mode 100644 index 00000000..57206494 --- /dev/null +++ b/kind/testing-only-cert-key/rekor_key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEICnmFR7rXoJ3QujB9SzrKbVtXCikPXtEb2rs8EGgzYrSoAoGCCqGSM49 +AwEHoUQDQgAEnItR5lDp+1fPho5A2npEr9CygZ3lVGXB6jc0MAS/bez9PxUlPacS +XrlASWbaMaLIoporoKnYhoGHd1oiiVq1lg== +-----END EC PRIVATE KEY----- diff --git a/sign-verify.md b/sign-verify.md index b4a1ea02..92b8f917 100644 --- a/sign-verify.md +++ b/sign-verify.md @@ -13,12 +13,11 @@ OPENSHIFT_APPS_SUBDOMAIN=apps.$(oc get dns cluster -o jsonpath='{ .spec.baseDoma The following assumes there exists a Keycloak `keycloak` in namespace `keycloak-system` ```shell -export KEYCLOAK_REALM=sigstore +export OIDC_AUTHENTICATION_REALM=sigstore export FULCIO_URL=https://fulcio.$OPENSHIFT_APPS_SUBDOMAIN -export KEYCLOAK_URL=https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN +export OIDC_ISSUER_URL=https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/$OIDC_AUTHENTICATION_REALM export REKOR_URL=https://rekor.$OPENSHIFT_APPS_SUBDOMAIN export TUF_URL=https://tuf.$OPENSHIFT_APPS_SUBDOMAIN -export KEYCLOAK_OIDC_ISSUER=$KEYCLOAK_URL/auth/realms/$KEYCLOAK_REALM ``` 2. Initialize the TUF roots @@ -32,10 +31,10 @@ Note: If you have used `cosign` previously, you may need to delete the `~/.sigst 3. Sign the desired container ```shell -cosign sign -y --fulcio-url=$FULCIO_URL --rekor-url=$REKOR_URL --oidc-issuer=$KEYCLOAK_OIDC_ISSUER +cosign sign -y --fulcio-url=$FULCIO_URL --rekor-url=$REKOR_URL --oidc-issuer=$OIDC_ISSUER_URL ``` -Authenticate with the Keycloak instance using the desired credentials. +Authenticate with the OIDC provider (Keycloak, here) using the desired credentials. 4. Verify the signed image @@ -76,7 +75,7 @@ oc exec -n cosign -- /bin/sh -c 'cosign initialize --mirror=$TUF_URL oc exec -n cosign -- /bin/sh -c 'cosign login -u -p ' ``` -4. Retrieve `id_token` from the keycloak provider. +4. Retrieve `id_token` from the OIDC provider. ``` curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=" \ @@ -84,15 +83,15 @@ curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \ -d "password=" \ -d "grant_type=password" \ -d "scope=openid" \ -/auth/realms//protocol/openid-connect/token +/protocol/openid-connect/token ``` 5. Sign the container. ``` -oc exec -n cosign -- /bin/sh -c 'cosign sign -y --fulcio-url=$FULCIO_URL --rekor-url=$REKOR_URL --oidc-issuer=$KEYCLOAK_OIDC_ISSUER --identity-token= ' +oc exec -n cosign -- /bin/sh -c 'cosign sign -y --fulcio-url=$FULCIO_URL --rekor-url=$REKOR_URL --oidc-issuer=$OIDC_ISSUER_URL --identity-token= ' ``` -6. Verify the signed image. +6. Verify the signed image. Again, this example assumes `Keycloak` is the OIDC provider. ```shell oc exec -n cosign -- /bin/sh -c 'cosign verify --rekor-url=$REKOR_URL --certificate-identity-regexp sigstore-user --certificate-oidc-issuer-regexp keycloak '