From e9ba64636ccf46346f5a7adf123f0e936663af85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20Mass=C3=A9?= Date: Thu, 15 Jun 2023 21:58:34 +0200 Subject: [PATCH] wip --- infrastructure/files/cosign-hook/cosign.sh | 24 --- infrastructure/files/init-hook/init.sh | 51 +++++++ .../stackrox-configure-hook/configure.yaml | 56 +++++-- infrastructure/templates/acs.yaml | 63 ++++++-- infrastructure/templates/devspaces.yaml | 4 +- infrastructure/templates/eshop-dev.yaml | 138 +----------------- ...mchartrepository.yaml => eshop-infra.yaml} | 110 +++++++++++++- infrastructure/templates/eshop-prod.yaml | 6 +- infrastructure/templates/eshop-test.yaml | 6 +- 9 files changed, 261 insertions(+), 197 deletions(-) delete mode 100644 infrastructure/files/cosign-hook/cosign.sh create mode 100644 infrastructure/files/init-hook/init.sh rename infrastructure/templates/{helmchartrepository.yaml => eshop-infra.yaml} (56%) diff --git a/infrastructure/files/cosign-hook/cosign.sh b/infrastructure/files/cosign-hook/cosign.sh deleted file mode 100644 index 9c347bf..0000000 --- a/infrastructure/files/cosign-hook/cosign.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -set -Eeuo pipefail - -mkdir -p /tmp/bin -curl -sfLo /tmp/bin/cosign https://github.com/sigstore/cosign/releases/download/v2.0.2/cosign-linux-amd64 -chmod 755 /tmp/bin/cosign -export PATH="/tmp/bin:$PATH" - -if ! oc get secret code-signature -n eshop-dev &>/dev/null; then - echo "========================================================================" - echo " Generating a keypair" - echo "========================================================================" - echo - - ## Move to /tmp before creating the keypair because of: - # Error: open cosign.pub: permission denied - # main.go:74: error during command execution: open cosign.pub: permission denied - cd /tmp - - COSIGN_PASSWORD=dummy cosign generate-key-pair k8s://eshop-dev/code-signature -fi - -exit 0 diff --git a/infrastructure/files/init-hook/init.sh b/infrastructure/files/init-hook/init.sh new file mode 100644 index 0000000..d3e196d --- /dev/null +++ b/infrastructure/files/init-hook/init.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +set -Eeuo pipefail + +mkdir -p /tmp/bin +curl -sSfL -o /tmp/bin/yq https://github.com/mikefarah/yq/releases/download/v4.34.1/yq_linux_amd64 +curl -sSfL -o /tmp/bin/cosign https://github.com/sigstore/cosign/releases/download/v2.0.2/cosign-linux-amd64 +curl -sLo /tmp/bin/jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 +chmod 755 /tmp/bin/cosign /tmp/bin/yq /tmp/bin/jq +export PATH="/tmp/bin:$PATH" + +if ! oc get secret code-signature -n eshop-infra &>/dev/null; then + echo "========================================================================" + echo " Generating a keypair for code signature with cosign" + echo "========================================================================" + echo + + ## Move to /tmp before creating the keypair because of: + # Error: open cosign.pub: permission denied + # main.go:74: error during command execution: open cosign.pub: permission denied + cd /tmp + + COSIGN_PASSWORD=dummy cosign generate-key-pair k8s://eshop-infra/code-signature +fi + +echo +echo "========================================================================" +echo " Distributing the code signature keypair to relevant namespaces" +echo "========================================================================" +echo + +oc get secret code-signature -n eshop-infra -o yaml | yq eval 'del(.status, .metadata.resourceVersion, .metadata.uid, .metadata.namespace, .metadata.creationTimestamp, .metadata.selfLink, .metadata.managedFields)' - > /tmp/code-signature-secret.yaml +oc apply -f /tmp/code-signature-secret.yaml -n eshop-dev +oc apply -f /tmp/code-signature-secret.yaml -n stackrox + +echo +echo "========================================================================" +echo " Distributing the Stackrox CI/CD token to relevant namespaces" +echo "========================================================================" +echo + +while ! oc get secret stackrox-cicd-token -n stackrox &>/dev/null; do + echo "Secret not yet created..." + sleep 5 + +done + +oc get secret stackrox-cicd-token -n stackrox -o yaml | yq eval 'del(.status, .metadata.resourceVersion, .metadata.uid, .metadata.namespace, .metadata.creationTimestamp, .metadata.selfLink, .metadata.managedFields)' - > /tmp/cicd-token-secret.yaml +oc apply -f /tmp/cicd-token-secret.yaml -n eshop-dev + +exit 0 diff --git a/infrastructure/files/stackrox-configure-hook/configure.yaml b/infrastructure/files/stackrox-configure-hook/configure.yaml index a49cb60..e2fff56 100644 --- a/infrastructure/files/stackrox-configure-hook/configure.yaml +++ b/infrastructure/files/stackrox-configure-hook/configure.yaml @@ -41,7 +41,7 @@ api_version: v1 kind: Secret name: code-signature - namespace: eshop-dev + namespace: stackrox register: cosign_secret failed_when: cosign_secret.resources|length == 0 until: cosign_secret is succeeded @@ -76,6 +76,50 @@ retries: 60 delay: 5 + - name: Get K8s secret + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: stackrox-cicd-token + namespace: stackrox + register: cicd_token_secret + + - name: Create the CI/CD API Token + uri: + url: '{{ acs_api }}/apitokens/generate' + method: POST + status_code: "200" + validate_certs: '{{ validate_certs }}' + url_username: admin + url_password: '{{ central_admin_password }}' + body: '{{ token_creation }}' + body_format: json + force_basic_auth: yes + register: create_apitoken_response + changed_when: create_apitoken_response.status == 200 + when: cicd_token_secret.resources|length == 0 + vars: + token_creation: + name: tekton-pipelines + role: Continuous Integration + + - set_fact: + apitoken_value: '{{ create_apitoken_response.json.token }}' + when: cicd_token_secret.resources|length == 0 + + - name: Create the K8s Secret + kubernetes.core.k8s: + state: present + definition: + apiVersion: v1 + kind: Secret + metadata: + name: stackrox-cicd-token + namespace: stackrox + stringData: + token: '{{ apitoken_value }}' + when: apitoken_value is defined + - name: Find signature integrations uri: url: '{{ acs_api }}/signatureintegrations' @@ -183,16 +227,6 @@ rationale: The container image MUST be digitally signed in order to prevent tampering. remediation: Use cosign to sign this image. See https://docs.sigstore.dev/cosign/signing_with_containers/ scope: - - cluster: - label: - key: app - value: eshop-web - namespace: eshop-test - - cluster: - label: - key: app - value: eshop-api - namespace: eshop-test - cluster: label: key: app diff --git a/infrastructure/templates/acs.yaml b/infrastructure/templates/acs.yaml index 38e2421..cb69ade 100644 --- a/infrastructure/templates/acs.yaml +++ b/infrastructure/templates/acs.yaml @@ -1,5 +1,5 @@ -apiVersion: project.openshift.io/v1 -kind: Project +apiVersion: v1 +kind: Namespace metadata: annotations: argocd.argoproj.io/sync-wave: "0" @@ -16,7 +16,7 @@ apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: annotations: - argocd.argoproj.io/sync-wave: "5" + argocd.argoproj.io/sync-wave: "0" name: rhacs-operator namespace: rhacs-operator spec: @@ -37,8 +37,8 @@ spec: sourceNamespace: openshift-marketplace startingCSV: rhacs-operator.v4.0.1 --- -apiVersion: project.openshift.io/v1 -kind: Project +apiVersion: v1 +kind: Namespace metadata: annotations: argocd.argoproj.io/sync-wave: "10" @@ -100,6 +100,49 @@ spec: autoScaling: Disabled replicas: 3 scannerComponent: Enabled + # Listen on pain HTTP so that we can expose the central through a Route + customize: + envVars: + - name: ROX_PLAINTEXT_ENDPOINTS + value: http@8080 +--- +kind: Service +apiVersion: v1 +metadata: + annotations: + argocd.argoproj.io/sync-wave: "20" + name: central-plain + namespace: stackrox +spec: + ports: + - name: http + protocol: TCP + port: 8080 + targetPort: 8080 + type: ClusterIP + sessionAffinity: None + selector: + app: central +--- +kind: Route +apiVersion: route.openshift.io/v1 +metadata: + annotations: + argocd.argoproj.io/sync-wave: "20" + name: central-plain + namespace: stackrox +spec: + host: central.{{ .Values.openshiftDnsZone }} + to: + kind: Service + name: central-plain + weight: 100 + port: + targetPort: 8080 + tls: + termination: edge + insecureEdgeTerminationPolicy: Redirect + wildcardPolicy: None --- apiVersion: v1 kind: ServiceAccount @@ -168,7 +211,6 @@ metadata: data: {{ (.Files.Glob "files/stackrox-init-hook/*").AsConfig | indent 2 }} --- -{{ if false }} apiVersion: v1 kind: ConfigMap metadata: @@ -178,7 +220,6 @@ metadata: namespace: stackrox data: {{ (.Files.Glob "files/stackrox-configure-hook/*").AsConfig | indent 2 }} -{{ end }} --- apiVersion: batch/v1 kind: Job @@ -236,8 +277,7 @@ spec: admissionControl: listenOnUpdates: true bypass: BreakGlassAnnotation - # Temporarily disable this feature - contactImageScanners: DoNotScanInline # ScanIfMissing + contactImageScanners: ScanIfMissing listenOnCreates: true timeoutSeconds: 20 listenOnEvents: true @@ -256,7 +296,6 @@ spec: taintToleration: TolerateTaints clusterName: local-cluster --- -{{ if false }} apiVersion: batch/v1 kind: Job metadata: @@ -289,7 +328,3 @@ spec: configMap: name: stackrox-configure-hook defaultMode: 0755 -{{ end }} -# TODO: -# - scale down the ACS operator -# - patch the central route to Reencrypt diff --git a/infrastructure/templates/devspaces.yaml b/infrastructure/templates/devspaces.yaml index d343d82..3243834 100644 --- a/infrastructure/templates/devspaces.yaml +++ b/infrastructure/templates/devspaces.yaml @@ -1,5 +1,5 @@ -apiVersion: project.openshift.io/v1 -kind: Project +apiVersion: v1 +kind: Namespace metadata: annotations: argocd.argoproj.io/sync-wave: "0" diff --git a/infrastructure/templates/eshop-dev.yaml b/infrastructure/templates/eshop-dev.yaml index 43e3f90..6ff1c60 100644 --- a/infrastructure/templates/eshop-dev.yaml +++ b/infrastructure/templates/eshop-dev.yaml @@ -1,6 +1,5 @@ -{{ if false }} -apiVersion: project.openshift.io/v1 -kind: Project +apiVersion: v1 +kind: Namespace metadata: annotations: argocd.argoproj.io/sync-wave: "0" @@ -13,138 +12,6 @@ spec: finalizers: - kubernetes --- -apiVersion: v1 -kind: ServiceAccount -metadata: - annotations: - argocd.argoproj.io/sync-wave: "20" - name: cosign-hook - namespace: eshop-dev ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - annotations: - argocd.argoproj.io/sync-wave: "20" - name: cosign-hook - namespace: eshop-dev -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: edit -subjects: -- kind: ServiceAccount - name: cosign-hook - namespace: eshop-dev ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - annotations: - argocd.argoproj.io/sync-wave: "20" - name: secret-reader - namespace: eshop-dev -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list", "watch"] ---- -# The stackrox hook needs to be able to read the cosign public key in order to create the sigstore policy -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - annotations: - argocd.argoproj.io/sync-wave: "20" - name: stackrox-hook - namespace: eshop-dev -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: secret-reader -subjects: -- kind: ServiceAccount - name: stackrox-hook - namespace: stackrox ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - annotations: - argocd.argoproj.io/sync-wave: "20" - name: test-can-pull - namespace: eshop-dev -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:image-puller -subjects: -- kind: ServiceAccount - name: default - namespace: eshop-test ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - annotations: - argocd.argoproj.io/sync-wave: "20" - name: prod-can-pull - namespace: eshop-dev -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:image-puller -subjects: -- kind: ServiceAccount - name: default - namespace: eshop-prod ---- -apiVersion: v1 -kind: ConfigMap -metadata: - annotations: - argocd.argoproj.io/sync-wave: "20" - name: cosign-hook - namespace: eshop-dev -data: -{{ (.Files.Glob "files/cosign-hook/*").AsConfig | indent 2 }} ---- -apiVersion: batch/v1 -kind: Job -metadata: - annotations: - argocd.argoproj.io/sync-wave: "20" - name: cosign-hook - namespace: eshop-dev -spec: - backoffLimit: 30 - template: - spec: - containers: - - name: hook - command: - - /entrypoint/cosign.sh - args: [] - image: registry.redhat.io/openshift4/ose-cli:v4.13 - imagePullPolicy: IfNotPresent - env: - - name: USER - value: openshift - - name: HOME - value: /tmp - volumeMounts: - - mountPath: /entrypoint - name: cosign-hook - readOnly: true - serviceAccountName: cosign-hook - serviceAccount: cosign-hook - restartPolicy: OnFailure - terminationGracePeriodSeconds: 30 - volumes: - - name: cosign-hook - configMap: - name: cosign-hook - defaultMode: 0755 ---- apiVersion: image.openshift.io/v1 kind: ImageStream metadata: @@ -166,4 +33,3 @@ metadata: spec: lookupPolicy: local: false -{{ end }} \ No newline at end of file diff --git a/infrastructure/templates/helmchartrepository.yaml b/infrastructure/templates/eshop-infra.yaml similarity index 56% rename from infrastructure/templates/helmchartrepository.yaml rename to infrastructure/templates/eshop-infra.yaml index ebdd0a6..ba3b4f3 100644 --- a/infrastructure/templates/helmchartrepository.yaml +++ b/infrastructure/templates/eshop-infra.yaml @@ -1,5 +1,5 @@ -apiVersion: project.openshift.io/v1 -kind: Project +apiVersion: v1 +kind: Namespace metadata: annotations: argocd.argoproj.io/sync-wave: "0" @@ -133,3 +133,109 @@ spec: name: eShop Helm Charts connectionConfig: url: http://helm-repository.eshop-infra.svc:8080 +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + annotations: + argocd.argoproj.io/sync-wave: "20" + name: init-hook + namespace: eshop-infra +--- +# The init-hook needs to be able to create a Secret in the stackrox namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + annotations: + argocd.argoproj.io/sync-wave: "20" + name: init-hook-can-admin + namespace: stackrox +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: admin +subjects: +- kind: ServiceAccount + name: init-hook + namespace: eshop-infra +--- +# The init-hook needs to be able to create a Secret in the eshop-dev namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + annotations: + argocd.argoproj.io/sync-wave: "20" + name: init-hook-can-admin + namespace: eshop-dev +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: admin +subjects: +- kind: ServiceAccount + name: init-hook + namespace: eshop-infra +--- +# The init-hook needs to be able to create a Secret in the eshop-infra namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + annotations: + argocd.argoproj.io/sync-wave: "20" + name: init-hook-can-admin + namespace: eshop-infra +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: admin +subjects: +- kind: ServiceAccount + name: init-hook + namespace: eshop-infra +--- +apiVersion: v1 +kind: ConfigMap +metadata: + annotations: + argocd.argoproj.io/sync-wave: "20" + name: init-hook + namespace: eshop-infra +data: +{{ (.Files.Glob "files/init-hook/*").AsConfig | indent 2 }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + annotations: + argocd.argoproj.io/sync-wave: "20" + name: init-hook + namespace: eshop-infra +spec: + backoffLimit: 30 + template: + spec: + containers: + - name: hook + command: + - /entrypoint/init.sh + args: [] + image: registry.redhat.io/openshift4/ose-cli:v4.13 + imagePullPolicy: IfNotPresent + env: + - name: USER + value: openshift + - name: HOME + value: /tmp + volumeMounts: + - mountPath: /entrypoint + name: init-hook + readOnly: true + serviceAccountName: init-hook + serviceAccount: init-hook + restartPolicy: OnFailure + terminationGracePeriodSeconds: 30 + volumes: + - name: init-hook + configMap: + name: init-hook + defaultMode: 0755 diff --git a/infrastructure/templates/eshop-prod.yaml b/infrastructure/templates/eshop-prod.yaml index 785cc29..ca3e4ff 100644 --- a/infrastructure/templates/eshop-prod.yaml +++ b/infrastructure/templates/eshop-prod.yaml @@ -1,6 +1,5 @@ -{{ if false }} -apiVersion: project.openshift.io/v1 -kind: Project +apiVersion: v1 +kind: Namespace metadata: annotations: argocd.argoproj.io/sync-wave: "0" @@ -28,4 +27,3 @@ subjects: - kind: ServiceAccount name: pipeline namespace: eshop-dev -{{ end }} \ No newline at end of file diff --git a/infrastructure/templates/eshop-test.yaml b/infrastructure/templates/eshop-test.yaml index 974d9ac..e366c97 100644 --- a/infrastructure/templates/eshop-test.yaml +++ b/infrastructure/templates/eshop-test.yaml @@ -1,6 +1,5 @@ -{{ if false }} -apiVersion: project.openshift.io/v1 -kind: Project +apiVersion: v1 +kind: Namespace metadata: annotations: argocd.argoproj.io/sync-wave: "0" @@ -28,4 +27,3 @@ subjects: - kind: ServiceAccount name: pipeline namespace: eshop-dev -{{ end }} \ No newline at end of file