From 0fe52e1ae6a6342eaa9cd12ecfc4a31910444f56 Mon Sep 17 00:00:00 2001 From: rhacs-bot Date: Tue, 11 Jun 2024 16:33:52 +0000 Subject: [PATCH] Publish Helm Charts for version 4.3.8 (#143) Source-Version: e20344e381af04b5974bf9528e0ec24bcb76f5e2 --- 4.3.8/central-services/.helmignore | 23 + 4.3.8/central-services/Chart.yaml | 7 + 4.3.8/central-services/README.md | 179 ++++++ .../assets/Red_Hat-Hat_icon.png | Bin 0 -> 7393 bytes .../central-services/assets/StackRox_icon.png | Bin 0 -> 13406 bytes .../config-templates/scanner/config.yaml.tpl | 48 ++ .../config/central/config.yaml.default | 7 + .../config/central/endpoints.yaml.default | 31 + .../config/centraldb/pg_hba.conf.default | 103 ++++ .../config/centraldb/postgresql.conf.default | 29 + .../config/proxy-config.yaml.default | 26 + .../internal/bootstrap-defaults.yaml.tpl | 16 + .../internal/config-shape.yaml | 163 ++++++ 4.3.8/central-services/internal/defaults.yaml | 175 ++++++ .../internal/expandables.yaml | 48 ++ .../internal/platforms/default.yaml | 2 + .../internal/platforms/gke.yaml | 2 + .../internal/scanner-config-shape.yaml | 40 ++ .../templates/00-additional-ca.yaml | 21 + .../templates/00-image-pull-secret.yaml | 18 + .../templates/00-injected-ca-bundle.yaml | 15 + .../templates/00-proxy-config-secret.yaml | 20 + .../templates/00-stackrox-application.yaml | 122 ++++ .../templates/00-storage-class.yaml | 27 + .../01-central-00-db-serviceaccount.yaml | 16 + .../01-central-00-serviceaccount.yaml | 19 + .../01-central-01-license-secret.yaml | 21 + .../templates/01-central-02-db-psps.yaml | 81 +++ .../templates/01-central-02-db-security.yaml | 82 +++ .../templates/01-central-02-psps.yaml | 80 +++ .../templates/01-central-02-security.yaml | 85 +++ .../01-central-03-diagnostics-rbac.yaml | 45 ++ .../01-central-04-htpasswd-secret.yaml | 22 + .../01-central-05-db-tls-secret.yaml | 23 + .../templates/01-central-05-tls-secret.yaml | 30 + ...01-central-06-default-tls-cert-secret.yaml | 22 + .../templates/01-central-08-configmap.yaml | 14 + .../templates/01-central-08-db-configmap.yaml | 17 + .../01-central-08-external-db-configmap.yaml | 29 + .../01-central-09-endpoints-config.yaml | 17 + .../01-central-10-db-networkpolicy.yaml | 27 + .../01-central-10-networkpolicy.yaml | 65 +++ .../templates/01-central-11-db-pvc.yaml | 66 +++ .../templates/01-central-11-pvc.yaml | 63 ++ .../templates/01-central-12-central-db.yaml | 196 +++++++ .../templates/01-central-13-deployment.yaml | 271 +++++++++ .../templates/01-central-14-service.yaml | 43 ++ .../templates/01-central-15-exposure.yaml | 95 ++++ .../02-scanner-00-serviceaccount.yaml | 19 + .../templates/02-scanner-01-psps.yaml | 69 +++ .../templates/02-scanner-01-security.yaml | 78 +++ .../02-scanner-02-db-password-secret.yaml | 27 + .../templates/02-scanner-03-tls-secret.yaml | 55 ++ .../02-scanner-04-scanner-config.yaml | 18 + .../02-scanner-05-network-policy.yaml | 91 +++ .../templates/02-scanner-06-deployment.yaml | 296 ++++++++++ .../templates/02-scanner-07-service.yaml | 99 ++++ .../templates/02-scanner-08-hpa.yaml | 25 + .../templates/99-generated-values-secret.yaml | 25 + .../templates/99-openshift-monitoring.yaml | 134 +++++ 4.3.8/central-services/templates/NOTES.txt | 56 ++ .../templates/_central_endpoints.tpl | 59 ++ .../templates/_central_setup.tpl | 140 +++++ 4.3.8/central-services/templates/_crypto.tpl | 239 ++++++++ 4.3.8/central-services/templates/_dict.tpl | 142 +++++ 4.3.8/central-services/templates/_expand.tpl | 96 ++++ 4.3.8/central-services/templates/_format.tpl | 14 + 4.3.8/central-services/templates/_helpers.tpl | 68 +++ .../templates/_image-pull-secrets.tpl | 85 +++ 4.3.8/central-services/templates/_images.tpl | 34 ++ 4.3.8/central-services/templates/_init.tpl | 285 ++++++++++ .../templates/_injected-ca-bundle.tpl | 29 + 4.3.8/central-services/templates/_labels.tpl | 31 + 4.3.8/central-services/templates/_lookup.tpl | 40 ++ .../central-services/templates/_metadata.tpl | 194 +++++++ .../central-services/templates/_openshift.tpl | 47 ++ 4.3.8/central-services/templates/_psp.tpl | 19 + .../central-services/templates/_reporting.tpl | 34 ++ .../templates/_scanner_init.tpl | 40 ++ .../values-private.yaml.example | 178 ++++++ .../values-public.yaml.example | 538 ++++++++++++++++++ 4.3.8/central-services/values.yaml | 364 ++++++++++++ 4.3.8/secured-cluster-services/.helmignore | 23 + 4.3.8/secured-cluster-services/Chart.yaml | 7 + 4.3.8/secured-cluster-services/README.md | 468 +++++++++++++++ .../assets/Red_Hat-Hat_icon.png | Bin 0 -> 7393 bytes .../assets/StackRox_icon.png | Bin 0 -> 13406 bytes .../config-templates/scanner/config.yaml.tpl | 48 ++ .../internal/cluster-config.yaml.tpl | 33 ++ .../internal/compatibility-translation.yaml | 137 +++++ .../internal/config-shape.yaml | 162 ++++++ .../internal/defaults/00-bootstrap.yaml | 15 + .../internal/defaults/10-env.yaml | 11 + .../internal/defaults/20-tls-files.yaml | 23 + .../internal/defaults/30-base-config.yaml | 117 ++++ .../internal/defaults/40-resources.yaml | 44 ++ .../internal/defaults/50-images.yaml | 114 ++++ .../internal/defaults/60-sccs.yaml | 2 + .../internal/defaults/70-scanner.yaml | 38 ++ .../internal/defaults/whats-this.md | 39 ++ .../internal/expandables.yaml | 44 ++ .../internal/scanner-config-shape.yaml | 40 ++ .../scripts/fetch-secrets.sh | 41 ++ .../fetched-secrets-bundle-ca-only.yaml.tpl | 9 + .../scripts/fetched-secrets-bundle.yaml.tpl | 35 ++ .../sensor-chart-upgrade.md | 159 ++++++ .../00-collector-image-pull-secrets.yaml | 18 + .../templates/00-injected-ca-bundle.yaml | 15 + .../templates/00-main-image-pull-secrets.yaml | 18 + .../02-scanner-00-serviceaccount.yaml | 19 + .../templates/02-scanner-01-psps.yaml | 69 +++ .../templates/02-scanner-01-security.yaml | 78 +++ .../02-scanner-02-db-password-secret.yaml | 27 + .../02-scanner-04-scanner-config.yaml | 18 + .../02-scanner-05-network-policy.yaml | 91 +++ .../templates/02-scanner-06-deployment.yaml | 296 ++++++++++ .../templates/02-scanner-07-service.yaml | 99 ++++ .../templates/02-scanner-08-hpa.yaml | 25 + .../templates/NOTES.txt | 40 ++ .../templates/_compatibility.tpl | 51 ++ .../templates/_crypto.tpl | 239 ++++++++ .../templates/_defaults.tpl | 35 ++ .../templates/_dict.tpl | 142 +++++ .../templates/_expand.tpl | 96 ++++ .../templates/_format.tpl | 14 + .../templates/_helpers.tpl | 68 +++ .../templates/_image-pull-secrets.tpl | 85 +++ .../templates/_images.tpl | 34 ++ .../templates/_init.tpl | 257 +++++++++ .../templates/_injected-ca-bundle.tpl | 29 + .../templates/_labels.tpl | 31 + .../templates/_lookup.tpl | 40 ++ .../templates/_metadata.tpl | 194 +++++++ .../templates/_openshift.tpl | 47 ++ .../templates/_psp.tpl | 19 + .../templates/_reporting.tpl | 34 ++ .../templates/_scanner_init.tpl | 40 ++ .../templates/additional-ca-sensor.yaml | 19 + .../admission-controller-netpol.yaml | 46 ++ .../admission-controller-pod-security.yaml | 76 +++ .../templates/admission-controller-rbac.yaml | 50 ++ .../templates/admission-controller-scc.yaml | 46 ++ .../admission-controller-secret.yaml | 30 + .../templates/admission-controller.yaml | 246 ++++++++ .../templates/cluster-config.yaml | 14 + .../templates/collector-netpol.yaml | 44 ++ .../templates/collector-pod-security.yaml | 72 +++ .../templates/collector-rbac.yaml | 16 + .../templates/collector-scc.yaml | 91 +++ .../templates/collector-secret.yaml | 30 + .../templates/collector.yaml | 218 +++++++ .../templates/openshift-monitoring.yaml | 121 ++++ .../templates/sensor-netpol.yaml | 88 +++ .../templates/sensor-pod-security.yaml | 82 +++ .../templates/sensor-rbac.yaml | 293 ++++++++++ .../templates/sensor-scc.yaml | 47 ++ .../templates/sensor-secret.yaml | 30 + .../templates/sensor.yaml | 280 +++++++++ .../templates/service-ca.yaml | 16 + .../templates/upgrader-serviceaccount.yaml | 36 ++ .../values-private.yaml.example | 19 + .../values-public.yaml.example | 465 +++++++++++++++ .../values-scanner.yaml.example | 92 +++ 4.3.8/secured-cluster-services/values.yaml | 9 + README.md | 12 +- latest | 2 +- opensource/index.yaml | 244 ++++---- .../stackrox-central-services-400.3.8.tgz | Bin 0 -> 75342 bytes ...ckrox-secured-cluster-services-400.3.8.tgz | Bin 0 -> 76161 bytes rhacs/4.3.8/central-services/.helmignore | 23 + rhacs/4.3.8/central-services/Chart.yaml | 7 + rhacs/4.3.8/central-services/README.md | 179 ++++++ .../assets/Red_Hat-Hat_icon.png | Bin 0 -> 7393 bytes .../central-services/assets/StackRox_icon.png | Bin 0 -> 13406 bytes .../config-templates/scanner/config.yaml.tpl | 48 ++ .../config/central/config.yaml.default | 7 + .../config/central/endpoints.yaml.default | 31 + .../config/centraldb/pg_hba.conf.default | 103 ++++ .../config/centraldb/postgresql.conf.default | 29 + .../config/proxy-config.yaml.default | 26 + .../internal/bootstrap-defaults.yaml.tpl | 16 + .../internal/config-shape.yaml | 163 ++++++ .../central-services/internal/defaults.yaml | 175 ++++++ .../internal/expandables.yaml | 48 ++ .../internal/platforms/default.yaml | 2 + .../internal/platforms/gke.yaml | 2 + .../internal/scanner-config-shape.yaml | 40 ++ .../templates/00-additional-ca.yaml | 21 + .../templates/00-image-pull-secret.yaml | 18 + .../templates/00-injected-ca-bundle.yaml | 15 + .../templates/00-proxy-config-secret.yaml | 20 + .../templates/00-stackrox-application.yaml | 122 ++++ .../templates/00-storage-class.yaml | 27 + .../01-central-00-db-serviceaccount.yaml | 16 + .../01-central-00-serviceaccount.yaml | 19 + .../01-central-01-license-secret.yaml | 21 + .../templates/01-central-02-db-psps.yaml | 81 +++ .../templates/01-central-02-db-security.yaml | 82 +++ .../templates/01-central-02-psps.yaml | 80 +++ .../templates/01-central-02-security.yaml | 85 +++ .../01-central-03-diagnostics-rbac.yaml | 45 ++ .../01-central-04-htpasswd-secret.yaml | 22 + .../01-central-05-db-tls-secret.yaml | 23 + .../templates/01-central-05-tls-secret.yaml | 30 + ...01-central-06-default-tls-cert-secret.yaml | 22 + .../templates/01-central-08-configmap.yaml | 14 + .../templates/01-central-08-db-configmap.yaml | 17 + .../01-central-08-external-db-configmap.yaml | 29 + .../01-central-09-endpoints-config.yaml | 17 + .../01-central-10-db-networkpolicy.yaml | 27 + .../01-central-10-networkpolicy.yaml | 65 +++ .../templates/01-central-11-db-pvc.yaml | 66 +++ .../templates/01-central-11-pvc.yaml | 63 ++ .../templates/01-central-12-central-db.yaml | 196 +++++++ .../templates/01-central-13-deployment.yaml | 271 +++++++++ .../templates/01-central-14-service.yaml | 43 ++ .../templates/01-central-15-exposure.yaml | 95 ++++ .../02-scanner-00-serviceaccount.yaml | 19 + .../templates/02-scanner-01-psps.yaml | 69 +++ .../templates/02-scanner-01-security.yaml | 78 +++ .../02-scanner-02-db-password-secret.yaml | 27 + .../templates/02-scanner-03-tls-secret.yaml | 55 ++ .../02-scanner-04-scanner-config.yaml | 18 + .../02-scanner-05-network-policy.yaml | 91 +++ .../templates/02-scanner-06-deployment.yaml | 296 ++++++++++ .../templates/02-scanner-07-service.yaml | 99 ++++ .../templates/02-scanner-08-hpa.yaml | 25 + .../templates/99-generated-values-secret.yaml | 25 + .../templates/99-openshift-monitoring.yaml | 134 +++++ .../central-services/templates/NOTES.txt | 56 ++ .../templates/_central_endpoints.tpl | 59 ++ .../templates/_central_setup.tpl | 140 +++++ .../central-services/templates/_crypto.tpl | 239 ++++++++ .../central-services/templates/_dict.tpl | 142 +++++ .../central-services/templates/_expand.tpl | 96 ++++ .../central-services/templates/_format.tpl | 14 + .../central-services/templates/_helpers.tpl | 68 +++ .../templates/_image-pull-secrets.tpl | 85 +++ .../central-services/templates/_images.tpl | 34 ++ .../central-services/templates/_init.tpl | 285 ++++++++++ .../templates/_injected-ca-bundle.tpl | 29 + .../central-services/templates/_labels.tpl | 31 + .../central-services/templates/_lookup.tpl | 40 ++ .../central-services/templates/_metadata.tpl | 194 +++++++ .../central-services/templates/_openshift.tpl | 47 ++ .../4.3.8/central-services/templates/_psp.tpl | 19 + .../central-services/templates/_reporting.tpl | 34 ++ .../templates/_scanner_init.tpl | 40 ++ .../values-private.yaml.example | 178 ++++++ .../values-public.yaml.example | 538 ++++++++++++++++++ rhacs/4.3.8/central-services/values.yaml | 364 ++++++++++++ .../secured-cluster-services/.helmignore | 23 + .../4.3.8/secured-cluster-services/Chart.yaml | 7 + .../4.3.8/secured-cluster-services/README.md | 468 +++++++++++++++ .../assets/Red_Hat-Hat_icon.png | Bin 0 -> 7393 bytes .../assets/StackRox_icon.png | Bin 0 -> 13406 bytes .../config-templates/scanner/config.yaml.tpl | 48 ++ .../internal/cluster-config.yaml.tpl | 33 ++ .../internal/compatibility-translation.yaml | 137 +++++ .../internal/config-shape.yaml | 162 ++++++ .../internal/defaults/00-bootstrap.yaml | 15 + .../internal/defaults/10-env.yaml | 11 + .../internal/defaults/20-tls-files.yaml | 23 + .../internal/defaults/30-base-config.yaml | 117 ++++ .../internal/defaults/40-resources.yaml | 44 ++ .../internal/defaults/50-images.yaml | 114 ++++ .../internal/defaults/60-sccs.yaml | 2 + .../internal/defaults/70-scanner.yaml | 38 ++ .../internal/defaults/whats-this.md | 39 ++ .../internal/expandables.yaml | 44 ++ .../internal/scanner-config-shape.yaml | 40 ++ .../scripts/fetch-secrets.sh | 41 ++ .../fetched-secrets-bundle-ca-only.yaml.tpl | 9 + .../scripts/fetched-secrets-bundle.yaml.tpl | 35 ++ .../sensor-chart-upgrade.md | 159 ++++++ .../00-collector-image-pull-secrets.yaml | 18 + .../templates/00-injected-ca-bundle.yaml | 15 + .../templates/00-main-image-pull-secrets.yaml | 18 + .../02-scanner-00-serviceaccount.yaml | 19 + .../templates/02-scanner-01-psps.yaml | 69 +++ .../templates/02-scanner-01-security.yaml | 78 +++ .../02-scanner-02-db-password-secret.yaml | 27 + .../02-scanner-04-scanner-config.yaml | 18 + .../02-scanner-05-network-policy.yaml | 91 +++ .../templates/02-scanner-06-deployment.yaml | 296 ++++++++++ .../templates/02-scanner-07-service.yaml | 99 ++++ .../templates/02-scanner-08-hpa.yaml | 25 + .../templates/NOTES.txt | 40 ++ .../templates/_compatibility.tpl | 51 ++ .../templates/_crypto.tpl | 239 ++++++++ .../templates/_defaults.tpl | 35 ++ .../templates/_dict.tpl | 142 +++++ .../templates/_expand.tpl | 96 ++++ .../templates/_format.tpl | 14 + .../templates/_helpers.tpl | 68 +++ .../templates/_image-pull-secrets.tpl | 85 +++ .../templates/_images.tpl | 34 ++ .../templates/_init.tpl | 257 +++++++++ .../templates/_injected-ca-bundle.tpl | 29 + .../templates/_labels.tpl | 31 + .../templates/_lookup.tpl | 40 ++ .../templates/_metadata.tpl | 194 +++++++ .../templates/_openshift.tpl | 47 ++ .../templates/_psp.tpl | 19 + .../templates/_reporting.tpl | 34 ++ .../templates/_scanner_init.tpl | 40 ++ .../templates/additional-ca-sensor.yaml | 19 + .../admission-controller-netpol.yaml | 46 ++ .../admission-controller-pod-security.yaml | 76 +++ .../templates/admission-controller-rbac.yaml | 50 ++ .../templates/admission-controller-scc.yaml | 46 ++ .../admission-controller-secret.yaml | 30 + .../templates/admission-controller.yaml | 246 ++++++++ .../templates/cluster-config.yaml | 14 + .../templates/collector-netpol.yaml | 44 ++ .../templates/collector-pod-security.yaml | 72 +++ .../templates/collector-rbac.yaml | 16 + .../templates/collector-scc.yaml | 91 +++ .../templates/collector-secret.yaml | 30 + .../templates/collector.yaml | 218 +++++++ .../templates/openshift-monitoring.yaml | 121 ++++ .../templates/sensor-netpol.yaml | 88 +++ .../templates/sensor-pod-security.yaml | 82 +++ .../templates/sensor-rbac.yaml | 293 ++++++++++ .../templates/sensor-scc.yaml | 47 ++ .../templates/sensor-secret.yaml | 30 + .../templates/sensor.yaml | 280 +++++++++ .../templates/service-ca.yaml | 16 + .../templates/upgrader-serviceaccount.yaml | 36 ++ .../values-private.yaml.example | 19 + .../values-public.yaml.example | 465 +++++++++++++++ .../values-scanner.yaml.example | 92 +++ .../secured-cluster-services/values.yaml | 9 + 333 files changed, 25484 insertions(+), 118 deletions(-) create mode 100644 4.3.8/central-services/.helmignore create mode 100644 4.3.8/central-services/Chart.yaml create mode 100644 4.3.8/central-services/README.md create mode 100644 4.3.8/central-services/assets/Red_Hat-Hat_icon.png create mode 100644 4.3.8/central-services/assets/StackRox_icon.png create mode 100644 4.3.8/central-services/config-templates/scanner/config.yaml.tpl create mode 100644 4.3.8/central-services/config/central/config.yaml.default create mode 100644 4.3.8/central-services/config/central/endpoints.yaml.default create mode 100644 4.3.8/central-services/config/centraldb/pg_hba.conf.default create mode 100644 4.3.8/central-services/config/centraldb/postgresql.conf.default create mode 100644 4.3.8/central-services/config/proxy-config.yaml.default create mode 100644 4.3.8/central-services/internal/bootstrap-defaults.yaml.tpl create mode 100644 4.3.8/central-services/internal/config-shape.yaml create mode 100644 4.3.8/central-services/internal/defaults.yaml create mode 100644 4.3.8/central-services/internal/expandables.yaml create mode 100644 4.3.8/central-services/internal/platforms/default.yaml create mode 100644 4.3.8/central-services/internal/platforms/gke.yaml create mode 100644 4.3.8/central-services/internal/scanner-config-shape.yaml create mode 100644 4.3.8/central-services/templates/00-additional-ca.yaml create mode 100644 4.3.8/central-services/templates/00-image-pull-secret.yaml create mode 100644 4.3.8/central-services/templates/00-injected-ca-bundle.yaml create mode 100644 4.3.8/central-services/templates/00-proxy-config-secret.yaml create mode 100644 4.3.8/central-services/templates/00-stackrox-application.yaml create mode 100644 4.3.8/central-services/templates/00-storage-class.yaml create mode 100644 4.3.8/central-services/templates/01-central-00-db-serviceaccount.yaml create mode 100644 4.3.8/central-services/templates/01-central-00-serviceaccount.yaml create mode 100644 4.3.8/central-services/templates/01-central-01-license-secret.yaml create mode 100644 4.3.8/central-services/templates/01-central-02-db-psps.yaml create mode 100644 4.3.8/central-services/templates/01-central-02-db-security.yaml create mode 100644 4.3.8/central-services/templates/01-central-02-psps.yaml create mode 100644 4.3.8/central-services/templates/01-central-02-security.yaml create mode 100644 4.3.8/central-services/templates/01-central-03-diagnostics-rbac.yaml create mode 100644 4.3.8/central-services/templates/01-central-04-htpasswd-secret.yaml create mode 100644 4.3.8/central-services/templates/01-central-05-db-tls-secret.yaml create mode 100644 4.3.8/central-services/templates/01-central-05-tls-secret.yaml create mode 100644 4.3.8/central-services/templates/01-central-06-default-tls-cert-secret.yaml create mode 100644 4.3.8/central-services/templates/01-central-08-configmap.yaml create mode 100644 4.3.8/central-services/templates/01-central-08-db-configmap.yaml create mode 100644 4.3.8/central-services/templates/01-central-08-external-db-configmap.yaml create mode 100644 4.3.8/central-services/templates/01-central-09-endpoints-config.yaml create mode 100644 4.3.8/central-services/templates/01-central-10-db-networkpolicy.yaml create mode 100644 4.3.8/central-services/templates/01-central-10-networkpolicy.yaml create mode 100644 4.3.8/central-services/templates/01-central-11-db-pvc.yaml create mode 100644 4.3.8/central-services/templates/01-central-11-pvc.yaml create mode 100644 4.3.8/central-services/templates/01-central-12-central-db.yaml create mode 100644 4.3.8/central-services/templates/01-central-13-deployment.yaml create mode 100644 4.3.8/central-services/templates/01-central-14-service.yaml create mode 100644 4.3.8/central-services/templates/01-central-15-exposure.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-00-serviceaccount.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-01-psps.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-01-security.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-02-db-password-secret.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-03-tls-secret.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-04-scanner-config.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-05-network-policy.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-06-deployment.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-07-service.yaml create mode 100644 4.3.8/central-services/templates/02-scanner-08-hpa.yaml create mode 100644 4.3.8/central-services/templates/99-generated-values-secret.yaml create mode 100644 4.3.8/central-services/templates/99-openshift-monitoring.yaml create mode 100644 4.3.8/central-services/templates/NOTES.txt create mode 100644 4.3.8/central-services/templates/_central_endpoints.tpl create mode 100644 4.3.8/central-services/templates/_central_setup.tpl create mode 100644 4.3.8/central-services/templates/_crypto.tpl create mode 100644 4.3.8/central-services/templates/_dict.tpl create mode 100644 4.3.8/central-services/templates/_expand.tpl create mode 100644 4.3.8/central-services/templates/_format.tpl create mode 100644 4.3.8/central-services/templates/_helpers.tpl create mode 100644 4.3.8/central-services/templates/_image-pull-secrets.tpl create mode 100644 4.3.8/central-services/templates/_images.tpl create mode 100644 4.3.8/central-services/templates/_init.tpl create mode 100644 4.3.8/central-services/templates/_injected-ca-bundle.tpl create mode 100644 4.3.8/central-services/templates/_labels.tpl create mode 100644 4.3.8/central-services/templates/_lookup.tpl create mode 100644 4.3.8/central-services/templates/_metadata.tpl create mode 100644 4.3.8/central-services/templates/_openshift.tpl create mode 100644 4.3.8/central-services/templates/_psp.tpl create mode 100644 4.3.8/central-services/templates/_reporting.tpl create mode 100644 4.3.8/central-services/templates/_scanner_init.tpl create mode 100644 4.3.8/central-services/values-private.yaml.example create mode 100644 4.3.8/central-services/values-public.yaml.example create mode 100644 4.3.8/central-services/values.yaml create mode 100644 4.3.8/secured-cluster-services/.helmignore create mode 100644 4.3.8/secured-cluster-services/Chart.yaml create mode 100644 4.3.8/secured-cluster-services/README.md create mode 100644 4.3.8/secured-cluster-services/assets/Red_Hat-Hat_icon.png create mode 100644 4.3.8/secured-cluster-services/assets/StackRox_icon.png create mode 100644 4.3.8/secured-cluster-services/config-templates/scanner/config.yaml.tpl create mode 100644 4.3.8/secured-cluster-services/internal/cluster-config.yaml.tpl create mode 100644 4.3.8/secured-cluster-services/internal/compatibility-translation.yaml create mode 100644 4.3.8/secured-cluster-services/internal/config-shape.yaml create mode 100644 4.3.8/secured-cluster-services/internal/defaults/00-bootstrap.yaml create mode 100644 4.3.8/secured-cluster-services/internal/defaults/10-env.yaml create mode 100644 4.3.8/secured-cluster-services/internal/defaults/20-tls-files.yaml create mode 100644 4.3.8/secured-cluster-services/internal/defaults/30-base-config.yaml create mode 100644 4.3.8/secured-cluster-services/internal/defaults/40-resources.yaml create mode 100644 4.3.8/secured-cluster-services/internal/defaults/50-images.yaml create mode 100644 4.3.8/secured-cluster-services/internal/defaults/60-sccs.yaml create mode 100644 4.3.8/secured-cluster-services/internal/defaults/70-scanner.yaml create mode 100644 4.3.8/secured-cluster-services/internal/defaults/whats-this.md create mode 100644 4.3.8/secured-cluster-services/internal/expandables.yaml create mode 100644 4.3.8/secured-cluster-services/internal/scanner-config-shape.yaml create mode 100755 4.3.8/secured-cluster-services/scripts/fetch-secrets.sh create mode 100644 4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl create mode 100644 4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl create mode 100644 4.3.8/secured-cluster-services/sensor-chart-upgrade.md create mode 100644 4.3.8/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml create mode 100644 4.3.8/secured-cluster-services/templates/00-injected-ca-bundle.yaml create mode 100644 4.3.8/secured-cluster-services/templates/00-main-image-pull-secrets.yaml create mode 100644 4.3.8/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml create mode 100644 4.3.8/secured-cluster-services/templates/02-scanner-01-psps.yaml create mode 100644 4.3.8/secured-cluster-services/templates/02-scanner-01-security.yaml create mode 100644 4.3.8/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml create mode 100644 4.3.8/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml create mode 100644 4.3.8/secured-cluster-services/templates/02-scanner-05-network-policy.yaml create mode 100644 4.3.8/secured-cluster-services/templates/02-scanner-06-deployment.yaml create mode 100644 4.3.8/secured-cluster-services/templates/02-scanner-07-service.yaml create mode 100644 4.3.8/secured-cluster-services/templates/02-scanner-08-hpa.yaml create mode 100644 4.3.8/secured-cluster-services/templates/NOTES.txt create mode 100644 4.3.8/secured-cluster-services/templates/_compatibility.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_crypto.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_defaults.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_dict.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_expand.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_format.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_helpers.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_image-pull-secrets.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_images.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_init.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_injected-ca-bundle.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_labels.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_lookup.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_metadata.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_openshift.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_psp.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_reporting.tpl create mode 100644 4.3.8/secured-cluster-services/templates/_scanner_init.tpl create mode 100644 4.3.8/secured-cluster-services/templates/additional-ca-sensor.yaml create mode 100644 4.3.8/secured-cluster-services/templates/admission-controller-netpol.yaml create mode 100644 4.3.8/secured-cluster-services/templates/admission-controller-pod-security.yaml create mode 100644 4.3.8/secured-cluster-services/templates/admission-controller-rbac.yaml create mode 100644 4.3.8/secured-cluster-services/templates/admission-controller-scc.yaml create mode 100644 4.3.8/secured-cluster-services/templates/admission-controller-secret.yaml create mode 100644 4.3.8/secured-cluster-services/templates/admission-controller.yaml create mode 100644 4.3.8/secured-cluster-services/templates/cluster-config.yaml create mode 100644 4.3.8/secured-cluster-services/templates/collector-netpol.yaml create mode 100644 4.3.8/secured-cluster-services/templates/collector-pod-security.yaml create mode 100644 4.3.8/secured-cluster-services/templates/collector-rbac.yaml create mode 100644 4.3.8/secured-cluster-services/templates/collector-scc.yaml create mode 100644 4.3.8/secured-cluster-services/templates/collector-secret.yaml create mode 100644 4.3.8/secured-cluster-services/templates/collector.yaml create mode 100644 4.3.8/secured-cluster-services/templates/openshift-monitoring.yaml create mode 100644 4.3.8/secured-cluster-services/templates/sensor-netpol.yaml create mode 100644 4.3.8/secured-cluster-services/templates/sensor-pod-security.yaml create mode 100644 4.3.8/secured-cluster-services/templates/sensor-rbac.yaml create mode 100644 4.3.8/secured-cluster-services/templates/sensor-scc.yaml create mode 100644 4.3.8/secured-cluster-services/templates/sensor-secret.yaml create mode 100644 4.3.8/secured-cluster-services/templates/sensor.yaml create mode 100644 4.3.8/secured-cluster-services/templates/service-ca.yaml create mode 100644 4.3.8/secured-cluster-services/templates/upgrader-serviceaccount.yaml create mode 100644 4.3.8/secured-cluster-services/values-private.yaml.example create mode 100644 4.3.8/secured-cluster-services/values-public.yaml.example create mode 100644 4.3.8/secured-cluster-services/values-scanner.yaml.example create mode 100644 4.3.8/secured-cluster-services/values.yaml create mode 100644 opensource/stackrox-central-services-400.3.8.tgz create mode 100644 opensource/stackrox-secured-cluster-services-400.3.8.tgz create mode 100644 rhacs/4.3.8/central-services/.helmignore create mode 100644 rhacs/4.3.8/central-services/Chart.yaml create mode 100644 rhacs/4.3.8/central-services/README.md create mode 100644 rhacs/4.3.8/central-services/assets/Red_Hat-Hat_icon.png create mode 100644 rhacs/4.3.8/central-services/assets/StackRox_icon.png create mode 100644 rhacs/4.3.8/central-services/config-templates/scanner/config.yaml.tpl create mode 100644 rhacs/4.3.8/central-services/config/central/config.yaml.default create mode 100644 rhacs/4.3.8/central-services/config/central/endpoints.yaml.default create mode 100644 rhacs/4.3.8/central-services/config/centraldb/pg_hba.conf.default create mode 100644 rhacs/4.3.8/central-services/config/centraldb/postgresql.conf.default create mode 100644 rhacs/4.3.8/central-services/config/proxy-config.yaml.default create mode 100644 rhacs/4.3.8/central-services/internal/bootstrap-defaults.yaml.tpl create mode 100644 rhacs/4.3.8/central-services/internal/config-shape.yaml create mode 100644 rhacs/4.3.8/central-services/internal/defaults.yaml create mode 100644 rhacs/4.3.8/central-services/internal/expandables.yaml create mode 100644 rhacs/4.3.8/central-services/internal/platforms/default.yaml create mode 100644 rhacs/4.3.8/central-services/internal/platforms/gke.yaml create mode 100644 rhacs/4.3.8/central-services/internal/scanner-config-shape.yaml create mode 100644 rhacs/4.3.8/central-services/templates/00-additional-ca.yaml create mode 100644 rhacs/4.3.8/central-services/templates/00-image-pull-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/00-injected-ca-bundle.yaml create mode 100644 rhacs/4.3.8/central-services/templates/00-proxy-config-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/00-stackrox-application.yaml create mode 100644 rhacs/4.3.8/central-services/templates/00-storage-class.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-00-db-serviceaccount.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-00-serviceaccount.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-01-license-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-02-db-psps.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-02-db-security.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-02-psps.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-02-security.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-03-diagnostics-rbac.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-04-htpasswd-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-05-db-tls-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-05-tls-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-06-default-tls-cert-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-08-configmap.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-08-db-configmap.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-08-external-db-configmap.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-09-endpoints-config.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-10-db-networkpolicy.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-10-networkpolicy.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-11-db-pvc.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-11-pvc.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-12-central-db.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-13-deployment.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-14-service.yaml create mode 100644 rhacs/4.3.8/central-services/templates/01-central-15-exposure.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-00-serviceaccount.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-01-psps.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-01-security.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-02-db-password-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-03-tls-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-04-scanner-config.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-05-network-policy.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-06-deployment.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-07-service.yaml create mode 100644 rhacs/4.3.8/central-services/templates/02-scanner-08-hpa.yaml create mode 100644 rhacs/4.3.8/central-services/templates/99-generated-values-secret.yaml create mode 100644 rhacs/4.3.8/central-services/templates/99-openshift-monitoring.yaml create mode 100644 rhacs/4.3.8/central-services/templates/NOTES.txt create mode 100644 rhacs/4.3.8/central-services/templates/_central_endpoints.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_central_setup.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_crypto.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_dict.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_expand.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_format.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_helpers.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_image-pull-secrets.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_images.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_init.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_injected-ca-bundle.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_labels.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_lookup.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_metadata.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_openshift.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_psp.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_reporting.tpl create mode 100644 rhacs/4.3.8/central-services/templates/_scanner_init.tpl create mode 100644 rhacs/4.3.8/central-services/values-private.yaml.example create mode 100644 rhacs/4.3.8/central-services/values-public.yaml.example create mode 100644 rhacs/4.3.8/central-services/values.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/.helmignore create mode 100644 rhacs/4.3.8/secured-cluster-services/Chart.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/README.md create mode 100644 rhacs/4.3.8/secured-cluster-services/assets/Red_Hat-Hat_icon.png create mode 100644 rhacs/4.3.8/secured-cluster-services/assets/StackRox_icon.png create mode 100644 rhacs/4.3.8/secured-cluster-services/config-templates/scanner/config.yaml.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/cluster-config.yaml.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/compatibility-translation.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/config-shape.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/defaults/00-bootstrap.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/defaults/10-env.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/defaults/20-tls-files.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/defaults/30-base-config.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/defaults/40-resources.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/defaults/50-images.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/defaults/60-sccs.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/defaults/70-scanner.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/defaults/whats-this.md create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/expandables.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/internal/scanner-config-shape.yaml create mode 100755 rhacs/4.3.8/secured-cluster-services/scripts/fetch-secrets.sh create mode 100644 rhacs/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/sensor-chart-upgrade.md create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/00-injected-ca-bundle.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/00-main-image-pull-secrets.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/02-scanner-01-psps.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/02-scanner-01-security.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/02-scanner-05-network-policy.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/02-scanner-06-deployment.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/02-scanner-07-service.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/02-scanner-08-hpa.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/NOTES.txt create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_compatibility.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_crypto.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_defaults.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_dict.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_expand.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_format.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_helpers.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_image-pull-secrets.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_images.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_init.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_injected-ca-bundle.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_labels.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_lookup.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_metadata.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_openshift.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_psp.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_reporting.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/_scanner_init.tpl create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/additional-ca-sensor.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/admission-controller-netpol.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/admission-controller-pod-security.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/admission-controller-rbac.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/admission-controller-scc.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/admission-controller-secret.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/admission-controller.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/cluster-config.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/collector-netpol.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/collector-pod-security.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/collector-rbac.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/collector-scc.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/collector-secret.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/collector.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/openshift-monitoring.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/sensor-netpol.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/sensor-pod-security.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/sensor-rbac.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/sensor-scc.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/sensor-secret.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/sensor.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/service-ca.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/templates/upgrader-serviceaccount.yaml create mode 100644 rhacs/4.3.8/secured-cluster-services/values-private.yaml.example create mode 100644 rhacs/4.3.8/secured-cluster-services/values-public.yaml.example create mode 100644 rhacs/4.3.8/secured-cluster-services/values-scanner.yaml.example create mode 100644 rhacs/4.3.8/secured-cluster-services/values.yaml diff --git a/4.3.8/central-services/.helmignore b/4.3.8/central-services/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/4.3.8/central-services/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/4.3.8/central-services/Chart.yaml b/4.3.8/central-services/Chart.yaml new file mode 100644 index 0000000..922645d --- /dev/null +++ b/4.3.8/central-services/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 # Can probably be generalized to v1 later. TODO(ROX-5502). +name: stackrox-central-services +icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/Red_Hat-Hat_icon.png +description: Helm Chart for StackRox Central Service +type: application +version: 400.3.8 +appVersion: 4.3.8 diff --git a/4.3.8/central-services/README.md b/4.3.8/central-services/README.md new file mode 100644 index 0000000..f62a658 --- /dev/null +++ b/4.3.8/central-services/README.md @@ -0,0 +1,179 @@ +# StackRox Kubernetes Security Platform - Central Services Helm Chart + +This Helm chart allows you to deploy the central services of the StackRox +Kubernetes Security Platform: StackRox Central and StackRox Scanner. + +If you want to install Red Hat Advanced Cluster Security, refer to +[Installing quickly using Helm charts](https://docs.openshift.com/acs/installing/installing_helm/install-helm-quick.html) +for up to date information. + +## Prerequisites + +To deploy the central services for the StackRox Kubernetes Security platform +using Helm, you must: +- Have at least version 3.1 of the Helm tool installed on your machine + +## Add the Canonical Chart Location as a Helm Repository + +The canonical repository for StackRox Helm charts is https://charts.stackrox.io. +To use StackRox Helm charts on your machine, run +```sh +helm repo add stackrox https://charts.stackrox.io +``` +This command only needs to be run once on your machine. Whenever you are deploying +or upgrading a chart from a remote repository, it is advisable to run +```sh +helm repo update +``` +beforehand. + +## Deploy Central Services Using Helm + +The basic command for deploying the central services is +```sh +helm install -n stackrox --create-namespace \ + --set central.persistence.none=true \ + stackrox-central-services stackrox/stackrox-central-services +``` +If you have a copy of this chart on your machine, you can also reference the +path to this copy instead of `stackrox/stackrox-central-services` above. + +In case you use image mirroring or otherwise access StackRox container images from non-standard location, +you may also need to provide image pull credentials. +There are several ways to inject the required credentials (if any) into the installation process: + +- **Explicitly specify username and password:** Use this if you are using a registry that supports username/password + authentication. Pass the following arguments to the `helm install` command: + ```sh + --set imagePullSecrets.username= --set imagePullSecrets.password= + ``` +- **Use pre-existing image pull secrets:** If you already have one or several image pull secrets + created in the namespace to which you are deploying, you can reference these in the following + way (we assume that your secrets are called `pull-secret-1` and `pull-secret-2`): + ```sh + --set imagePullSecrets.useExisting="pull-secret-1;pull-secret-2" + ``` +- **Do not use image pull secrets:** If you are pulling your images from quay.io/stackrox-io or a registry in a private + network that does not require authentication, or if the default service account in the namespace + to which you are deploying is already configured with appropriate image pull secrets, you do + not need to specify any additional image pull secrets. + +### Accessing the StackRox Portal After Deployment + +Once you have deployed the StackRox Kubernetes Security Platform Central Services via +`helm install`, you will see an information text on the console that contains any things to +note, or warnings encountered during the installation text. In particular, it instructs you +how to connect to your Central deployment via port-forward (if you have not configured an +exposure method, see below), and the administrator password to use for the initial login. + +### Applying Custom Configuration Options + +This Helm chart has many different configuration options. For simple use cases, these can be +set directly on the `helm install` command line; however, we generally recommend that you +store your configuration in a dedicated file. + +#### Using the `--set` family of command-line flags + +This approach is the quickest way to customize the deployment, but it does not work for +more complex configuration settings. Via the `--set` and `--set-file` flags, which need to be +appended to your `helm install` invocation, you can inject configuration values into the +installation process. Here are some examples: +- **Deploy StackRox in offline mode:** This configures StackRox in a way such that it will not + reach out to any external endpoints. + ```sh + --set env.offlineMode=true + ``` +- **Configure a fixed administrator password:** This sets the password with which you log in to + the StackRox portal as an administrator. If you do not configure a password yourself, one will + be created for you and printed as part of the installation notes. + ```sh + --set central.adminPassword.value=mysupersecretpassword + ``` + +#### Using configuration YAML files and the `-f` command-line flag + +To ensure the best possible upgrade experience, it is recommended that you store all custom +configuration options in two files: `values-public.yaml` and `values-private.yaml`. The former +contains all non-sensitive configuration options (such as whether to run in offline mode), and the +latter contains all sensitive configuration options (such as the administrator password, or +custom TLS certificates). The `values-public.yaml` file can be stored in, for example, your Git +repository, while the `values-private.yaml` file should be stored in a secrets management +system. + +There is a large number of configuration options that cannot all be discussed in minute detail +in this README file. However, the Helm chart contains example configuration files +`values-public.yaml.example` and `values-private.yaml.example`, that list all the available +configuration options, along with documentation. The following is just a brief example of what +can be configured via those files: +- **`values-public.yaml`:** + ```yaml + env: + offlineMode: true # run in offline mode + + central: + # Use custom resource overrides for central + resources: + requests: + cpu: 4 + memory: "8Gi" + limits: + cpu: 8 + memory: "16Gi" + + # Expose central via a LoadBalancer service + exposure: + loadBalancer: + enabled: true + + scanner: + # Run without StackRox Scanner (NOT RECOMMENDED) + disable: true + + customize: + # Apply the important-service=true label for all objects managed by this chart. + labels: + important-service: true + # Set the CLUSTER=important-cluster environment variable for all containers in the + # central deployment: + central: + envVars: + CLUSTER: important-cluster + ``` +- **`values-private.yaml`**: + ```yaml + central: + # Configure a default TLS certificate (public cert + private key) for central + defaultTLS: + cert: | + -----BEGIN CERTIFICATE----- + MII... + -----END CERTIFICATE----- + key: | + -----BEGIN EC PRIVATE KEY----- + MHc... + -----END EC PRIVATE KEY----- + ``` + +After you have created these YAML files, you can inject the configuration options into the +installation process via the `-f` flag, i.e., by appending the following options to the +`helm install` invocation: +```sh +-f values-public.yaml -f values-private.yaml +``` + +### Changing Configuration Options After Deployment + +If you wish to make any changes to the deployment, simply change the configuration options +in your `values-public.yaml` and/or `values-private.yaml` file(s), and inject them into an +`helm upgrade` invocation: +```sh +helm upgrade -n stackrox stackrox-central-services stackrox/stackrox-central-services \ + -f values-public.yaml \ + -f values-private.yaml +``` +Under most circumstances, you will not need to supply the `values-private.yaml` file, unless +you want changes to sensitive configuration options to be applied. + +Of course you can also specify configuration values via the `--set` or `--set-file` command-line +flags. However, these options will be forgotten with the next `helm upgrade` invocation, unless +you supply them again. diff --git a/4.3.8/central-services/assets/Red_Hat-Hat_icon.png b/4.3.8/central-services/assets/Red_Hat-Hat_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fae985e3b0e5cfbcd1aa58e4a5b9d99f0274d937 GIT binary patch literal 7393 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 literal 0 HcmV?d00001 diff --git a/4.3.8/central-services/assets/StackRox_icon.png b/4.3.8/central-services/assets/StackRox_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3c136e3990a7382e8742c9079028abe00697c82c GIT binary patch literal 13406 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 literal 0 HcmV?d00001 diff --git a/4.3.8/central-services/config-templates/scanner/config.yaml.tpl b/4.3.8/central-services/config-templates/scanner/config.yaml.tpl new file mode 100644 index 0000000..5efc0b9 --- /dev/null +++ b/4.3.8/central-services/config-templates/scanner/config.yaml.tpl @@ -0,0 +1,48 @@ +{{- /* + This is the configuration file template for Scanner. + Except for in extremely rare circumstances, you DO NOT need to modify this file. + All config options that are possibly dynamic are templated out and can be modified + via `--set`/values-files specified via `-f`. + */ -}} + +# Configuration file for scanner. + +scanner: + centralEndpoint: https://central.{{ .Release.Namespace }}.svc + sensorEndpoint: https://sensor.{{ .Release.Namespace }}.svc + database: + # Database driver + type: pgsql + options: + # PostgreSQL Connection string + # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING + source: host=scanner-db.{{ .Release.Namespace }}.svc port=5432 user=postgres sslmode={{- if eq .Release.Namespace "stackrox" }}verify-full{{- else }}verify-ca{{- end }} statement_timeout=60000 + + # Number of elements kept in the cache + # Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database. + cachesize: 16384 + + api: + httpsPort: 8080 + grpcPort: 8443 + + updater: + # Frequency with which the scanner will poll for vulnerability updates. + interval: 5m + + logLevel: {{ ._rox.scanner.logLevel }} + + # The scanner intentionally avoids extracting or analyzing any files + # larger than the following default sizes to prevent DoS attacks. + # Leave these commented to use a reasonable default. + + # The max size of files in images that are extracted. + # Increasing this number increases memory pressure. + # maxExtractableFileSizeMB: 200 + # The max size of ELF executable files that are analyzed. + # Increasing this number may increase disk pressure. + # maxELFExecutableFileSizeMB: 800 + # The max size of image file reader buffer. Image file data beyond this limit are overflowed to temporary files on disk. + # maxImageFileReaderBufferSizeMB: 100 + + exposeMonitoring: false diff --git a/4.3.8/central-services/config/central/config.yaml.default b/4.3.8/central-services/config/central/config.yaml.default new file mode 100644 index 0000000..d85c852 --- /dev/null +++ b/4.3.8/central-services/config/central/config.yaml.default @@ -0,0 +1,7 @@ +maintenance: + safeMode: false # When set to true, Central will sleep forever on the next restart + compaction: + enabled: true + bucketFillFraction: .5 # This controls how densely to compact the buckets. Usually not advised to modify + freeFractionThreshold: 0.75 # This is the threshold for free bytes / total bytes after which compaction will occur + forceRollbackVersion: none # This is the config and target rollback version after upgrade complete. diff --git a/4.3.8/central-services/config/central/endpoints.yaml.default b/4.3.8/central-services/config/central/endpoints.yaml.default new file mode 100644 index 0000000..25549d6 --- /dev/null +++ b/4.3.8/central-services/config/central/endpoints.yaml.default @@ -0,0 +1,31 @@ +# Sample endpoints.yaml configuration for StackRox Central. +# +# # CAREFUL: If the following line is uncommented, do not expose the default endpoint on port 8443 by default. +# # This will break normal operation. +# disableDefault: true # if true, don't serve on :8443 +# endpoints: +# # Serve plaintext HTTP only on port 8080 +# - listen: ":8080" +# # Backend protocols, possible values are 'http' and 'grpc'. If unset or empty, assume both. +# protocols: +# - http +# tls: +# # Disable TLS. If this is not specified, assume TLS is enabled. +# disable: true +# # Serve HTTP and gRPC for sensors only on port 8444 +# - listen: ":8444" +# tls: +# # Which TLS certificates to serve, possible values are 'service' (StackRox-generated service certificates) +# # and 'default' (user-configured default TLS certificate). If unset or empty, assume both. +# serverCerts: +# - default +# - service +# # Client authentication settings. +# clientAuth: +# # Enforce TLS client authentication. If unset, do not enforce, only request certificates +# # opportunistically. +# required: true +# # Which TLS client CAs to serve, possible values are 'service' (CA for StackRox-generated service +# # certificates) and 'user' (CAs for PKI auth providers). If unset or empty, assume both. +# certAuthorities: # if not set, assume ["user", "service"] +# - service diff --git a/4.3.8/central-services/config/centraldb/pg_hba.conf.default b/4.3.8/central-services/config/centraldb/pg_hba.conf.default new file mode 100644 index 0000000..8229f95 --- /dev/null +++ b/4.3.8/central-services/config/centraldb/pg_hba.conf.default @@ -0,0 +1,103 @@ +# PostgreSQL Client Authentication Configuration File +# =================================================== +# +# Refer to the "Client Authentication" section in the PostgreSQL +# documentation for a complete description of this file. A short +# synopsis follows. +# +# This file controls: which hosts are allowed to connect, how clients +# are authenticated, which PostgreSQL user names they can use, which +# databases they can access. Records take one of these forms: +# +# local DATABASE USER METHOD [OPTIONS] +# host DATABASE USER ADDRESS METHOD [OPTIONS] +# hostssl DATABASE USER ADDRESS METHOD [OPTIONS] +# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] +# +# (The uppercase items must be replaced by actual values.) +# +# The first field is the connection type: "local" is a Unix-domain +# socket, "host" is either a plain or SSL-encrypted TCP/IP socket, +# "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a +# plain TCP/IP socket. +# +# DATABASE can be "all", "sameuser", "samerole", "replication", a +# database name, or a comma-separated list thereof. The "all" +# keyword does not match "replication". Access to replication +# must be enabled in a separate record (see example below). +# +# USER can be "all", a user name, a group name prefixed with "+", or a +# comma-separated list thereof. In both the DATABASE and USER fields +# you can also write a file name prefixed with "@" to include names +# from a separate file. +# +# ADDRESS specifies the set of hosts the record matches. It can be a +# host name, or it is made up of an IP address and a CIDR mask that is +# an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that +# specifies the number of significant bits in the mask. A host name +# that starts with a dot (.) matches a suffix of the actual host name. +# Alternatively, you can write an IP address and netmask in separate +# columns to specify the set of hosts. Instead of a CIDR-address, you +# can write "samehost" to match any of the server's own IP addresses, +# or "samenet" to match any address in any subnet that the server is +# directly connected to. +# +# METHOD can be "trust", "reject", "md5", "password", "scram-sha-256", +# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert". +# Note that "password" sends passwords in clear text; "md5" or +# "scram-sha-256" are preferred since they send encrypted passwords. +# +# OPTIONS are a set of options for the authentication in the format +# NAME=VALUE. The available options depend on the different +# authentication methods -- refer to the "Client Authentication" +# section in the documentation for a list of which options are +# available for which authentication methods. +# +# Database and user names containing spaces, commas, quotes and other +# special characters must be quoted. Quoting one of the keywords +# "all", "sameuser", "samerole" or "replication" makes the name lose +# its special character, and just match a database or username with +# that name. +# +# This file is read on server startup and when the server receives a +# SIGHUP signal. If you edit the file on a running system, you have to +# SIGHUP the server for the changes to take effect, run "pg_ctl reload", +# or execute "SELECT pg_reload_conf()". +# +# Put your actual configuration here +# ---------------------------------- +# +# If you want to allow non-local connections, you need to add more +# "host" records. In that case you will also need to make PostgreSQL +# listen on a non-local interface via the listen_addresses +# configuration parameter, or via the -i or -h command line switches. + +# CAUTION: Configuring the system for local "trust" authentication +# allows any local user to connect as any PostgreSQL user, including +# the database superuser. If you do not trust all your local users, +# use another authentication method. + + +# TYPE DATABASE USER ADDRESS METHOD + +# "local" is for Unix domain socket connections only +local all all scram-sha-256 +# IPv4 local connections: +host all all 127.0.0.1/32 scram-sha-256 +# IPv6 local connections: +host all all ::1/128 scram-sha-256 +# Allow replication connections from localhost, by a user with the +# replication privilege. +local replication all trust +host replication all 127.0.0.1/32 trust +host replication all ::1/128 trust + +### STACKROX MODIFIED +# Reject all non ssl connections from IPs +hostnossl all all 0.0.0.0/0 reject +hostnossl all all ::0/0 reject + +# Accept connections from ssl with password +hostssl all all 0.0.0.0/0 scram-sha-256 +hostssl all all ::0/0 scram-sha-256 +### diff --git a/4.3.8/central-services/config/centraldb/postgresql.conf.default b/4.3.8/central-services/config/centraldb/postgresql.conf.default new file mode 100644 index 0000000..057e7ea --- /dev/null +++ b/4.3.8/central-services/config/centraldb/postgresql.conf.default @@ -0,0 +1,29 @@ +hba_file = '/etc/stackrox.d/config/pg_hba.conf' +listen_addresses = '*' +max_connections = 200 +password_encryption = scram-sha-256 + +ssl = on +ssl_ca_file = '/run/secrets/stackrox.io/certs/root.crt' +ssl_cert_file = '/run/secrets/stackrox.io/certs/server.crt' +ssl_key_file = '/run/secrets/stackrox.io/certs/server.key' + +shared_buffers = 2GB +work_mem = 40MB +maintenance_work_mem = 512MB +effective_cache_size = 4GB + +dynamic_shared_memory_type = posix +max_wal_size = 5GB +min_wal_size = 80MB + +log_timezone = 'Etc/UTC' +datestyle = 'iso, mdy' +timezone = 'Etc/UTC' +lc_messages = 'en_US.utf8' +lc_monetary = 'en_US.utf8' # locale for monetary formatting +lc_numeric = 'en_US.utf8' # locale for number formatting +lc_time = 'en_US.utf8' # locale for time formatting + +default_text_search_config = 'pg_catalog.english' +shared_preload_libraries = 'pg_stat_statements' # StackRox customized \ No newline at end of file diff --git a/4.3.8/central-services/config/proxy-config.yaml.default b/4.3.8/central-services/config/proxy-config.yaml.default new file mode 100644 index 0000000..8692a77 --- /dev/null +++ b/4.3.8/central-services/config/proxy-config.yaml.default @@ -0,0 +1,26 @@ +# # NOTE: Both central and scanner should be restarted if this secret is changed. +# # While it is possible that some components will pick up the new proxy configuration +# # without a restart, it cannot be guaranteed that this will apply to every possible +# # integration etc. +# url: http://proxy.name:port +# username: username +# password: password +# # If the following value is set to true, the proxy wil NOT be excluded for the default hosts: +# # - *.stackrox, *.stackrox.svc +# # - localhost, localhost.localdomain, 127.0.0.0/8, ::1 +# # - *.local +# omitDefaultExcludes: false +# excludes: # hostnames (may include * components) for which not to use a proxy, like in-cluster repositories. +# - some.domain +# # The following configuration sections allow specifying a different proxy to be used for HTTP(S) connections. +# # If they are omitted, the above configuration is used for HTTP(S) connections as well as TCP connections. +# # If only the `http` section is given, it will be used for HTTPS connections as well. +# # Note: in most cases, a single, global proxy configuration is sufficient. +# http: +# url: http://http-proxy.name:port +# username: username +# password: password +# https: +# url: http://https-proxy.name:port +# username: username +# password: password diff --git a/4.3.8/central-services/internal/bootstrap-defaults.yaml.tpl b/4.3.8/central-services/internal/bootstrap-defaults.yaml.tpl new file mode 100644 index 0000000..8f8e559 --- /dev/null +++ b/4.3.8/central-services/internal/bootstrap-defaults.yaml.tpl @@ -0,0 +1,16 @@ +# This file contains defaults that need to be merged into our config struct before we can +# execute the "normal" defaulting logic. As a result, none of these values can be overridden +# by defaults specified in defaults.yaml and platforms/*.yaml - that is okay. + +{{- if eq .Release.Name "test-release" }} +{{- include "srox.warn" (list . "You are using a release name that is reserved for tests. In order to allow linting to work, certain checks have been relaxed. If you are deploying to a real environment, we recommend that you choose a different release name.") }} +allowNonstandardNamespace: true +allowNonstandardReleaseName: true +{{- else }} +allowNonstandardNamespace: false +allowNonstandardReleaseName: false +{{- end }} + +meta: + useLookup: true + fileOverrides: {} diff --git a/4.3.8/central-services/internal/config-shape.yaml b/4.3.8/central-services/internal/config-shape.yaml new file mode 100644 index 0000000..e1ce4b7 --- /dev/null +++ b/4.3.8/central-services/internal/config-shape.yaml @@ -0,0 +1,163 @@ +licenseKey: null # string +imagePullSecrets: + username: null # string + password: null # string + allowNone: null # bool + useExisting: null # string | [string] + useFromDefaultServiceAccount: null # bool +image: + registry: null # string +env: + installMethod: null # string + openshift: null # bool + istio: null # bool + platform: null # string + offlineMode: null # bool + proxyConfig: null # string | dict +ca: + cert: null # string + key: null # string + generate: null # bool +additionalCAs: null # string | [string] | dict +central: + telemetry: + enabled: null # bool + storage: + endpoint: null # string + key: null # string + config: null # string | dict + dbConfig: null # string | dict + endpointsConfig: null # string | dict + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + exposeMonitoring: null # bool + jwtSigner: + key: null # string + generate: null # bool + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + defaultTLS: + cert: null # string + key: null # string + reference: null # string + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + adminPassword: + value: null # string + generate: null # bool + htpasswd: null # string + resources: null # string | dict + persistence: + hostPath: null # string + persistentVolumeClaim: + claimName: null # string + createClaim: null # bool + storageClass: null # string + size: null # int | string + volume: + volumeSpec: null # dict + none: null # bool + exposure: + loadBalancer: + enabled: null # bool + port: null # int + ip: null # string + nodePort: + enabled: null # bool + port: null # int + route: + enabled: null # bool + host: null # string + declarativeConfiguration: + mounts: + configMaps: null # [string] + secrets: null # [string] + extraMounts: null # [dict] + db: + nodeSelector: null # string | dict + tolerations: null # [dict] + source: + connectionString: null # string + minConns: null # int + maxConns: null # int + statementTimeoutMs: null #int + configOverride: null # string + password: + value: null # string + generate: null # bool + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + resources: null # string | dict + persistence: + hostPath: null # string + persistentVolumeClaim: + claimName: null # string + createClaim: null # bool + storageClass: null # string + size: null # int | string + volume: + volumeSpec: null # dict + none: null # bool + extraMounts: null # [dict] +customize: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + central: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + db: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner-db: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + other: {} # dict +allowNonstandardNamespace: null # bool +allowNonstandardReleaseName: null # bool +enableOpenShiftMonitoring: null # bool +monitoring: + openshift: + enabled: null # bool +meta: + useLookup: null # bool + fileOverrides: {} # dict + apiServer: + version: null # string + overrideAPIResources: null # [string] + extraAPIResources: null # [string] + noCreateStorageClass: null # bool +globalPrefix: null # string +system: + createSCCs: null # bool + enablePodSecurityPolicies: null # bool diff --git a/4.3.8/central-services/internal/defaults.yaml b/4.3.8/central-services/internal/defaults.yaml new file mode 100644 index 0000000..a1eb08b --- /dev/null +++ b/4.3.8/central-services/internal/defaults.yaml @@ -0,0 +1,175 @@ +defaults: + + imagePullSecrets: + allowNone: false + useExisting: [] + useFromDefaultServiceAccount: true + + image: + registry: stackrox.io + + env: + offlineMode: false + + central: + config: "@config/central/config.yaml|config/central/config.yaml.default" + endpointsConfig: "@config/central/endpoints.yaml|config/central/endpoints.yaml.default" + + exposeMonitoring: false + + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Central is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + + image: + name: main + tag: 4.3.8 + + resources: + requests: + memory: "4Gi" + cpu: "1500m" + limits: + memory: "8Gi" + cpu: "4000m" + + exposure: + loadBalancer: + enabled: false + port: 443 + nodePort: + enabled: false + port: null + route: + enabled: false + db: + external: false + + source: + minConns: 10 + maxConns: 90 + statementTimeoutMs: 1200000 + + postgresConfig: "@config/centraldb/postgresql.conf|config/centraldb/postgresql.conf.default" + hbaConfig: "@config/centraldb/pg_hba.conf|config/centraldb/pg_hba.conf.default" + + image: + name: central-db + tag: 4.3.8 + + resources: + requests: + memory: "8Gi" + cpu: "4" + limits: + memory: "16Gi" + cpu: "8" + scanner: + disable: false + replicas: 3 + logLevel: INFO + mode: full + + autoscaling: + disable: false + minReplicas: 2 + maxReplicas: 5 + + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: + app: scanner + topologyKey: kubernetes.io/hostname + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + + resources: + requests: + memory: "1500Mi" + cpu: "1000m" + limits: + memory: "4Gi" + cpu: "2000m" + + image: + name: scanner + tag: 4.3.8 + + dbResources: + limits: + cpu: "2000m" + memory: "4Gi" + requests: + cpu: "200m" + memory: "200Mi" + + dbImage: + name: scanner-db + tag: 4.3.8 + + system: + createSCCs: true + +pvcDefaults: + claimName: "stackrox-db" + size: "100Gi" + +dbPVCDefaults: + claimName: "central-db" + size: "100Gi" diff --git a/4.3.8/central-services/internal/expandables.yaml b/4.3.8/central-services/internal/expandables.yaml new file mode 100644 index 0000000..75a3d11 --- /dev/null +++ b/4.3.8/central-services/internal/expandables.yaml @@ -0,0 +1,48 @@ +licenseKey: true +imagePullSecrets: + username: true + password: true +env: + proxyConfig: true +ca: + cert: true + key: true +central: + config: true + endpointsConfig: true + nodeSelector: true + jwtSigner: + key: true + serviceTLS: + cert: true + key: true + defaultTLS: + cert: true + key: true + adminPassword: + value: true + htpasswd: true + resources: true + db: + postgresConfig: true + hbaConfig: true + nodeSelector: true + serviceTLS: + cert: true + key: true + password: + value: true + resources: true +scanner: + resources: true + dbResources: true + nodeSelector: true + dbNodeSelector: true + dbPassword: + value: true + serviceTLS: + cert: true + key: true + dbServiceTLS: + cert: true + key: true diff --git a/4.3.8/central-services/internal/platforms/default.yaml b/4.3.8/central-services/internal/platforms/default.yaml new file mode 100644 index 0000000..180f5c8 --- /dev/null +++ b/4.3.8/central-services/internal/platforms/default.yaml @@ -0,0 +1,2 @@ +# Empty defaults file for the "default" platform. This file only exists to mark the platform +# name as valid. diff --git a/4.3.8/central-services/internal/platforms/gke.yaml b/4.3.8/central-services/internal/platforms/gke.yaml new file mode 100644 index 0000000..70d7b32 --- /dev/null +++ b/4.3.8/central-services/internal/platforms/gke.yaml @@ -0,0 +1,2 @@ +pvcDefaults: + storageClass: "stackrox-gke-ssd" diff --git a/4.3.8/central-services/internal/scanner-config-shape.yaml b/4.3.8/central-services/internal/scanner-config-shape.yaml new file mode 100644 index 0000000..da3b315 --- /dev/null +++ b/4.3.8/central-services/internal/scanner-config-shape.yaml @@ -0,0 +1,40 @@ +scanner: + mode: null # string + disable: null # bool + replicas: null # int + logLevel: null # string + nodeSelector: null # string | dict + dbNodeSelector: null # string | dict + tolerations: null # [dict] + dbTolerations: null # [dict] + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + affinity: null # dict + resources: null # string | dict + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + dbImage: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + dbResources: null # string | dict + dbPassword: + value: null # string + generate: null # bool + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + dbServiceTLS: + cert: null # string + key: null # string + generate: null # bool + exposeMonitoring: null # bool +system: + enablePodSecurityPolicies: null # bool diff --git a/4.3.8/central-services/templates/00-additional-ca.yaml b/4.3.8/central-services/templates/00-additional-ca.yaml new file mode 100644 index 0000000..67b0c2b --- /dev/null +++ b/4.3.8/central-services/templates/00-additional-ca.yaml @@ -0,0 +1,21 @@ +{{- include "srox.init" . -}} + +{{- if ._rox._additionalCAs }} +apiVersion: v1 +kind: Secret +metadata: + name: additional-ca + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "additional-ca") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "additional-ca") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + {{- range $name, $cert := ._rox._additionalCAs }} + {{ $name | quote }}: | + {{- $cert | nindent 4 }} + {{- end }} +{{- end }} diff --git a/4.3.8/central-services/templates/00-image-pull-secret.yaml b/4.3.8/central-services/templates/00-image-pull-secret.yaml new file mode 100644 index 0000000..1fc3e34 --- /dev/null +++ b/4.3.8/central-services/templates/00-image-pull-secret.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.imagePullSecrets._dockerAuths }} +apiVersion: v1 +kind: Secret +type: kubernetes.io/dockerconfigjson +metadata: + name: stackrox + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "stackrox") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "stackrox") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +data: + .dockerconfigjson: {{ dict "auths" ._rox.imagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/4.3.8/central-services/templates/00-injected-ca-bundle.yaml b/4.3.8/central-services/templates/00-injected-ca-bundle.yaml new file mode 100644 index 0000000..3289c2a --- /dev/null +++ b/4.3.8/central-services/templates/00-injected-ca-bundle.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} + +{{- if eq ._rox.env.openshift 4 }} +{{ $injectedCABundleName := printf "injected-cabundle-%s" .Release.Name }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $injectedCABundleName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" $injectedCABundleName) | nindent 4 }} + "config.openshift.io/inject-trusted-cabundle": "true" + annotations: + {{- include "srox.annotations" (list . "configmap" $injectedCABundleName) | nindent 4 }} +{{- end }} diff --git a/4.3.8/central-services/templates/00-proxy-config-secret.yaml b/4.3.8/central-services/templates/00-proxy-config-secret.yaml new file mode 100644 index 0000000..c357179 --- /dev/null +++ b/4.3.8/central-services/templates/00-proxy-config-secret.yaml @@ -0,0 +1,20 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.env._proxyConfig -}} +apiVersion: v1 +kind: Secret +metadata: + name: proxy-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "proxy-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "proxy-config") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + config.yaml: | + {{- ._rox.env._proxyConfig | nindent 4 }} + +{{ end }} diff --git a/4.3.8/central-services/templates/00-stackrox-application.yaml b/4.3.8/central-services/templates/00-stackrox-application.yaml new file mode 100644 index 0000000..6cdf9ca --- /dev/null +++ b/4.3.8/central-services/templates/00-stackrox-application.yaml @@ -0,0 +1,122 @@ +{{- include "srox.init" . -}} + +{{- if has "app.k8s.io/v1beta1/Application" ._rox._apiServer.apiResources -}} +apiVersion: app.k8s.io/v1beta1 +kind: Application +metadata: + name: stackrox + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "application" "stackrox") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "application" "stackrox") | nindent 4 }} + {{ if eq ._rox.image.registry "quay.io/stackrox-io" }} + kubernetes-engine.cloud.google.com/icon: "data:image/png;base64,{{ .Files.Get "assets/StackRox_icon.png" | b64enc }}" + {{ else }} + kubernetes-engine.cloud.google.com/icon: "data:image/png;base64,{{ .Files.Get "assets/Red_Hat-Hat_icon.png" | b64enc }}" + {{ end }} +spec: + descriptor: + type: StackRox + version: {{ .Chart.AppVersion | quote }} + description: |- + StackRox Kubernetes Security Platform + + Version {{ .Chart.AppVersion }} + + ## Thank you for installing StackRox! + +
+ + #### Support + + [Email support@stackrox.com](mailto:support@stackrox.com?cc=sales@stackrox.com&Subject=StackRox%20Support%20Question&Body=Dear%20StackRox%20support,) + + ## Connecting to StackRox + +
+ + #### Directly using a Load Balancer + + When deploying StackRox with the `Load Balancer` network configuration, the service can be accessed directly. + + $CONNECT + + #### Tunneling via Port Forward + + When deploying StackRox with the `Node Port` or `None` network configuration, the service must be accessed using a port forward tunnel. + + - Step 1 - Start the port forward tunnel to the StackRox Central service. + + ``` + $ kubectl -n stackrox port-forward svc/central 8443:443 + ``` + + - Step 2 - In a browser, [visit https://localhost:8443](https://localhost:8443) to access StackRox. + + keywords: + - "stackrox" + - "kube" + - "security" + maintainers: + - name: StackRox, Inc. + url: https://stackrox.com + owners: + - name: StackRox, Inc. + url: https://stackrox.com + links: + - description: StackRox Help Documentation + url: "https://help.stackrox.com" + + info: + - name: StackRox namespace + value: stackrox + - name: StackRox admin username + value: "admin" + + selector: + matchLabels: + app.kubernetes.io/name: stackrox + + componentKinds: + - group: '' + kind: ConfigMap + - group: '' + kind: Secret + - group: '' + kind: PersistentVolumeClaim + - group: '' + kind: PersistentVolume + - group: '' + kind: Service + - group: '' + kind: ServiceAccount + - group: rbac.authorization.k8s.io + kind: ClusterRole + - group: rbac.authorization.k8s.io + kind: ClusterRoleBinding + - group: apps + kind: Deployment + - group: networking.k8s.io + kind: NetworkPolicy + - group: rbac.authorization.k8s.io + kind: Role + - group: rbac.authorization.k8s.io + kind: RoleBinding + - group: route.openshift.io + kind: Route + - group: security.openshift.io + kind: SecurityContextConstraints + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + - group: autoscaling + kind: HorizontalPodAutoscaler + - group: storage.k8s.io + kind: StorageClass + - group: networking.istio.io + kind: DestinationRule +{{- if ._rox.system.enablePodSecurityPolicies }} + - group: policy + kind: PodSecurityPolicy +{{- end }} +{{- end }} diff --git a/4.3.8/central-services/templates/00-storage-class.yaml b/4.3.8/central-services/templates/00-storage-class.yaml new file mode 100644 index 0000000..4a5664e --- /dev/null +++ b/4.3.8/central-services/templates/00-storage-class.yaml @@ -0,0 +1,27 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.central.persistence._pvcCfg }} +{{- if ._rox.central.persistence._pvcCfg.storageClass -}} +{{- if eq ._rox.central.persistence._pvcCfg.storageClass "stackrox-gke-ssd" }} +{{- $lookupOut := dict -}} +{{- $storageClassName := include "srox.globalResourceName" (list . "stackrox-gke-ssd") -}} +{{- $_ := include "srox.safeLookup" (list . $lookupOut "storage.k8s.io/v1" "StorageClass" "" $storageClassName) -}} +{{- if and (not $lookupOut.result) (or .Release.IsInstall $lookupOut.reliable) (not ._rox.meta.noCreateStorageClass) -}} +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ $storageClassName }} + labels: + {{- include "srox.labels" (list . "storageclass" "stackrox-gke-ssd") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "storageclass" "stackrox-gke-ssd") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +provisioner: kubernetes.io/gce-pd +parameters: + type: pd-ssd +{{- end -}} +{{- end }} +{{- end -}} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-00-db-serviceaccount.yaml b/4.3.8/central-services/templates/01-central-00-db-serviceaccount.yaml new file mode 100644 index 0000000..782f4e6 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-00-db-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} +{{ if not ._rox.central.db.external -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: central-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "central-db") | nindent 4 }} +imagePullSecrets: + {{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} + {{- end }} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-00-serviceaccount.yaml b/4.3.8/central-services/templates/01-central-00-serviceaccount.yaml new file mode 100644 index 0000000..8c257f6 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-00-serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: central + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "central") | nindent 4 }} + {{- if and (eq ._rox.env.openshift 4) (not ._rox.env.managedServices) }} + serviceaccounts.openshift.io/oauth-redirectreference.main: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"central"}}' + serviceaccounts.openshift.io/oauth-redirecturi.main: "sso/providers/openshift/callback" + {{- end }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-01-license-secret.yaml b/4.3.8/central-services/templates/01-central-01-license-secret.yaml new file mode 100644 index 0000000..0d26dda --- /dev/null +++ b/4.3.8/central-services/templates/01-central-01-license-secret.yaml @@ -0,0 +1,21 @@ +{{- include "srox.init" . -}} + +{{- if ._rox._licenseKey -}} + +apiVersion: v1 +kind: Secret +metadata: + name: central-license + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-license") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-license") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + license.lic: | + {{- ._rox._licenseKey | nindent 4 }} + +{{ end }} diff --git a/4.3.8/central-services/templates/01-central-02-db-psps.yaml b/4.3.8/central-services/templates/01-central-02-db-psps.yaml new file mode 100644 index 0000000..4c81428 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-02-db-psps.yaml @@ -0,0 +1,81 @@ +{{- include "srox.init" . -}} + +{{- if and (not ._rox.central.db.external) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central-db-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-central-db-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-central-db-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-central-db") }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-central-db-psp + namespace: {{.Release.Namespace}} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-central-db-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-central-db-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-central-db-psp") }} +subjects: + - kind: ServiceAccount + name: central-db + namespace: {{.Release.Namespace}} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central-db") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-central-db") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + - 'hostPath' + - 'configMap' + {{- if ._rox.central.persistence.hostPath }} + allowedHostPaths: + {{- /* TODO(ROX-9807): Use a designated path for central-db for now. Need to move hostPath from central to central-db */}} + - pathPrefix: {{._rox.central.persistence.hostPath}}-db + {{- end}} + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 70 + max: 70 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 70 + max: 70 +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-02-db-security.yaml b/4.3.8/central-services/templates/01-central-02-db-security.yaml new file mode 100644 index 0000000..20ead97 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-02-db-security.yaml @@ -0,0 +1,82 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift (not ._rox.central.db.external) ._rox.system.createSCCs }} +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central-db") }} + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-central-db") | nindent 4 }} + annotations: + kubernetes.io/description: stackrox-central-db is the security constraint for the central database + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-central-db") | nindent 4 }} +allowHostDirVolumePlugin: {{ ._rox.central.persistence.hostPath | not | not }} +allowedCapabilities: [] +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +defaultAddCapabilities: [] +fsGroup: + type: MustRunAs + ranges: + - max: 70 + min: 70 +priority: 0 +readOnlyRootFilesystem: false +requiredDropCapabilities: [] +runAsUser: + type: MustRunAs + uid: 70 +seLinuxContext: + type: "RunAsAny" +seccompProfiles: + - '*' +users: + - system:serviceaccount:{{ .Release.Namespace }}:central-db +volumes: + - '*' +{{- else if eq ._rox.env.openshift 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-central-db-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-central-db-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-central-db-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - anyuid + {{- if ._rox.central.persistence.hostPath }} + - hostmount-anyuid + {{- end }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: central-db-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "central-db-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "central-db-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-central-db-scc +subjects: +- kind: ServiceAccount + name: central-db + namespace: {{.Release.Namespace}} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-02-psps.yaml b/4.3.8/central-services/templates/01-central-02-psps.yaml new file mode 100644 index 0000000..1ba51f5 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-02-psps.yaml @@ -0,0 +1,80 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-central-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-central-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-central") }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-central-psp + namespace: {{.Release.Namespace}} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-central-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-central-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-central-psp") }} +subjects: + - kind: ServiceAccount + name: central + namespace: {{.Release.Namespace}} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-central") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + - 'hostPath' + {{ if ._rox.central.persistence.hostPath -}} + allowedHostPaths: + - pathPrefix: {{ ._rox.central.persistence.hostPath }} + {{- end}} + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-02-security.yaml b/4.3.8/central-services/templates/01-central-02-security.yaml new file mode 100644 index 0000000..ee734a6 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-02-security.yaml @@ -0,0 +1,85 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} +--- + +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central") }} + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-central") | nindent 4 }} + annotations: + kubernetes.io/description: stackrox-central is the security constraint for the central server + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-central") | nindent 4 }} +allowHostDirVolumePlugin: {{ ._rox.central.persistence.hostPath | not | not }} +allowedCapabilities: [] +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +defaultAddCapabilities: [] +fsGroup: + type: MustRunAs + ranges: + - max: 4000 + min: 4000 +priority: 0 +readOnlyRootFilesystem: true +requiredDropCapabilities: [] +runAsUser: + type: MustRunAs + uid: 4000 +seLinuxContext: + type: MustRunAs +seccompProfiles: + - '*' +users: + - system:serviceaccount:{{ .Release.Namespace }}:central +volumes: + - '*' + +{{- else if eq ._rox.env.openshift 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-central-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-central-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-central-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - anyuid + {{- if ._rox.central.persistence.hostPath }} + - hostmount-anyuid + {{- end }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: central-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "central-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "central-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-central-scc +subjects: +- kind: ServiceAccount + name: central + namespace: {{.Release.Namespace}} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-03-diagnostics-rbac.yaml b/4.3.8/central-services/templates/01-central-03-diagnostics-rbac.yaml new file mode 100644 index 0000000..4c83007 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-03-diagnostics-rbac.yaml @@ -0,0 +1,45 @@ +{{- include "srox.init" . -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: stackrox-central-diagnostics + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "stackrox-central-diagnostics") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "stackrox-central-diagnostics") | nindent 4 }} +rules: +- apiGroups: + - '*' + resources: + - "deployments" + - "daemonsets" + - "replicasets" + - "configmaps" + - "services" + - "pods" + - "pods/log" + - "events" + - "namespaces" + verbs: + - get + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-central-diagnostics + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-central-diagnostics") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-central-diagnostics") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: stackrox-central-diagnostics +subjects: + - kind: ServiceAccount + name: central + namespace: {{ .Release.Namespace }} diff --git a/4.3.8/central-services/templates/01-central-04-htpasswd-secret.yaml b/4.3.8/central-services/templates/01-central-04-htpasswd-secret.yaml new file mode 100644 index 0000000..59b338e --- /dev/null +++ b/4.3.8/central-services/templates/01-central-04-htpasswd-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.central._adminPassword -}} +{{- if ._rox.central._adminPassword.htpasswd -}} +apiVersion: v1 +kind: Secret +metadata: + name: central-htpasswd + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-htpasswd") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-htpasswd") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + htpasswd: | + {{- ._rox.central._adminPassword.htpasswd | nindent 4 }} + +{{- end -}} +{{- end -}} diff --git a/4.3.8/central-services/templates/01-central-05-db-tls-secret.yaml b/4.3.8/central-services/templates/01-central-05-db-tls-secret.yaml new file mode 100644 index 0000000..3a3a1fa --- /dev/null +++ b/4.3.8/central-services/templates/01-central-05-db-tls-secret.yaml @@ -0,0 +1,23 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.central.db._serviceTLS ._rox._ca }} +apiVersion: v1 +kind: Secret +metadata: + name: central-db-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-db-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-db-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox._ca.Cert | nindent 4 }} + cert.pem: | + {{- ._rox.central.db._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.central.db._serviceTLS.Key | nindent 4 }} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-05-tls-secret.yaml b/4.3.8/central-services/templates/01-central-05-tls-secret.yaml new file mode 100644 index 0000000..1850d46 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-05-tls-secret.yaml @@ -0,0 +1,30 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox._ca ._rox.central._serviceTLS ._rox.central._jwtSigner -}} + +apiVersion: v1 +kind: Secret +metadata: + name: central-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox._ca.Cert | nindent 4 }} + ca-key.pem: | + {{- ._rox._ca.Key | nindent 4 }} + jwt-key.pem: | + {{- ._rox.central._jwtSigner.Key | nindent 4 }} + cert.pem: | + {{- ._rox.central._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.central._serviceTLS.Key | nindent 4 }} +{{- else if or ._rox.central._serviceTLS ._rox.central._jwtSigner }} +{{ include "srox.fail" "Service TLS certificates and/or JWT signer key can only be created/updated if all data AND the service CA are present/specified." }} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-06-default-tls-cert-secret.yaml b/4.3.8/central-services/templates/01-central-06-default-tls-cert-secret.yaml new file mode 100644 index 0000000..010444c --- /dev/null +++ b/4.3.8/central-services/templates/01-central-06-default-tls-cert-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} + +{{ if ._rox.central._defaultTLS }} + +apiVersion: v1 +kind: Secret +metadata: + name: central-default-tls-cert + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-default-tls-cert") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-default-tls-cert") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" +type: kubernetes.io/tls +stringData: + tls.crt: | + {{- ._rox.central._defaultTLS.Cert | nindent 4 }} + tls.key: | + {{- ._rox.central._defaultTLS.Key | nindent 4 }} + +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-08-configmap.yaml b/4.3.8/central-services/templates/01-central-08-configmap.yaml new file mode 100644 index 0000000..9420e59 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-08-configmap.yaml @@ -0,0 +1,14 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: central-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "central-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "central-config") | nindent 4 }} +data: + central-config.yaml: | + {{- ._rox.central._config | nindent 4 }} diff --git a/4.3.8/central-services/templates/01-central-08-db-configmap.yaml b/4.3.8/central-services/templates/01-central-08-db-configmap.yaml new file mode 100644 index 0000000..0a0a2c7 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-08-db-configmap.yaml @@ -0,0 +1,17 @@ +{{- include "srox.init" . -}} +{{- if not ._rox.central.db.external }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: central-db-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "central-db-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "central-db-config") | nindent 4 }} +data: + postgresql.conf: | + {{- ._rox.central.db._postgresConfig | nindent 4 }} + pg_hba.conf: | + {{- ._rox.central.db._hbaConfig | nindent 4 }} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-08-external-db-configmap.yaml b/4.3.8/central-services/templates/01-central-08-external-db-configmap.yaml new file mode 100644 index 0000000..48d2427 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-08-external-db-configmap.yaml @@ -0,0 +1,29 @@ +{{- include "srox.init" . -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: central-external-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "central-external-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "central-external-db") | nindent 4 }} +data: + central-external-db.yaml: | + centralDB: + {{- if ._rox.central.db.external }} + external: true + source: {{ ._rox.central.db.source.connectionString }} pool_min_conns={{ ._rox.central.db.source.minConns }} pool_max_conns={{ ._rox.central.db.source.maxConns }} + {{- else }} + external: false + source: > + host=central-db.{{ .Release.Namespace }}.svc + port=5432 + user=postgres + sslmode={{- if eq .Release.Namespace "stackrox" }}verify-full{{- else }}verify-ca{{- end }} + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + statement_timeout={{ ._rox.central.db.source.statementTimeoutMs }} + pool_min_conns={{ ._rox.central.db.source.minConns }} + pool_max_conns={{ ._rox.central.db.source.maxConns }} + client_encoding=UTF8 + {{- end }} diff --git a/4.3.8/central-services/templates/01-central-09-endpoints-config.yaml b/4.3.8/central-services/templates/01-central-09-endpoints-config.yaml new file mode 100644 index 0000000..fa6204e --- /dev/null +++ b/4.3.8/central-services/templates/01-central-09-endpoints-config.yaml @@ -0,0 +1,17 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.central._endpointsConfig -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: central-endpoints + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "central-endpoints") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "central-endpoints") | nindent 4 }} +data: + endpoints.yaml: | + {{- ._rox.central._endpointsConfig | nindent 4 }} + +{{- end -}} diff --git a/4.3.8/central-services/templates/01-central-10-db-networkpolicy.yaml b/4.3.8/central-services/templates/01-central-10-db-networkpolicy.yaml new file mode 100644 index 0000000..6cd2201 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-10-db-networkpolicy.yaml @@ -0,0 +1,27 @@ +{{- include "srox.init" . -}} +{{ if not ._rox.central.db.external -}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: central-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "central-db") | nindent 4 }} +spec: + policyTypes: + - Ingress + - Egress + ingress: + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 5432 + protocol: TCP + podSelector: + matchLabels: + app: central-db +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-10-networkpolicy.yaml b/4.3.8/central-services/templates/01-central-10-networkpolicy.yaml new file mode 100644 index 0000000..90fbd9d --- /dev/null +++ b/4.3.8/central-services/templates/01-central-10-networkpolicy.yaml @@ -0,0 +1,65 @@ +{{- include "srox.init" . -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-ext-to-central + namespace: {{.Release.Namespace}} + labels: + {{- include "srox.labels" (list . "networkpolicy" "allow-ext-to-central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "allow-ext-to-central") | nindent 4 }} +spec: + ingress: + {{- toYaml ._rox.central._netPolIngressRules | nindent 4 }} + podSelector: + matchLabels: + app: central + policyTypes: + - Ingress + +{{ if ._rox.central.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: central-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "central-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "central-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: central + policyTypes: + - Ingress +{{ end }} + +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: central-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "central-monitoring-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "central-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: central + policyTypes: + - Ingress +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-11-db-pvc.yaml b/4.3.8/central-services/templates/01-central-11-db-pvc.yaml new file mode 100644 index 0000000..656dfec --- /dev/null +++ b/4.3.8/central-services/templates/01-central-11-db-pvc.yaml @@ -0,0 +1,66 @@ +{{- include "srox.init" . -}} + +{{ if not ._rox.central.db.external -}} +{{ if ._rox.central.db.persistence._pvcCfg -}} +{{- $pvcCfg := ._rox.central.db.persistence._pvcCfg -}} +{{- $claimName := $pvcCfg.claimName -}} +{{/* In a multiple namespace setting, storageClassName is generated by globalResourceName */}} +{{- $storageClassName := "" }} +{{- if $pvcCfg.storageClass }} + {{- if eq $pvcCfg.storageClass "stackrox-gke-ssd" }} + {{- $storageClassName = include "srox.globalResourceName" (list . "stackrox-gke-ssd") }} + {{- else }} + {{- $storageClassName = $pvcCfg.storageClass }} +{{- end}} +{{- end}} +{{- if $pvcCfg.volume.volumeSpec }} +{{- $pvName := (print $claimName "-pv") -}} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ $pvName }} + labels: + {{- include "srox.labels" (list . "persistentvolume" $pvName) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolume" $pvName) | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end}} + capacity: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} + accessModes: + - ReadWriteOnce + claimRef: + namespace: {{ .Release.Namespace }} + name: {{ $claimName }} + {{- toYaml $pvcCfg.volume.volumeSpec | nindent 2 }} +--- +{{- end }} +{{- /* TODO(ROX-9807): Move customized PVC from Central to Central DB */}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ $claimName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "persistentvolumeclaim" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolumeclaim" "central-db") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-11-pvc.yaml b/4.3.8/central-services/templates/01-central-11-pvc.yaml new file mode 100644 index 0000000..0279278 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-11-pvc.yaml @@ -0,0 +1,63 @@ +{{- include "srox.init" . -}} + +{{ if ._rox.central.persistence._pvcCfg -}} +{{- $pvcCfg := ._rox.central.persistence._pvcCfg -}} +{{- $claimName := $pvcCfg.claimName -}} +{{/* In a multiple namespace setting, storageClassName is generated by globalResourceName */}} +{{- $storageClassName := "" }} +{{- if $pvcCfg.storageClass }} + {{- if eq $pvcCfg.storageClass "stackrox-gke-ssd" }} + {{- $storageClassName = include "srox.globalResourceName" (list . "stackrox-gke-ssd") }} + {{- else }} + {{- $storageClassName = $pvcCfg.storageClass }} + {{- end}} +{{- end}} +{{- if $pvcCfg.volume.volumeSpec }} +{{- $pvName := (print $claimName "-pv") -}} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ $pvName }} + labels: + {{- include "srox.labels" (list . "persistentvolume" $pvName) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolume" $pvName) | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end}} + capacity: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} + accessModes: + - ReadWriteOnce + claimRef: + namespace: {{ .Release.Namespace }} + name: {{ $claimName }} + {{- toYaml $pvcCfg.volume.volumeSpec | nindent 2 }} +--- +{{- end }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ $claimName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "persistentvolumeclaim" $claimName) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolumeclaim" $claimName) | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-12-central-db.yaml b/4.3.8/central-services/templates/01-central-12-central-db.yaml new file mode 100644 index 0000000..e48b466 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-12-central-db.yaml @@ -0,0 +1,196 @@ +{{- include "srox.init" . -}} + +{{ if not ._rox.central.db.external -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: central-db + namespace: {{ .Release.Namespace }} + labels: + app: central-db + {{- include "srox.labels" (list . "deployment" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "central-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: central-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: central-db + {{- include "srox.podLabels" (list . "deployment" "central-db") | nindent 8 }} + annotations: + {{- include "srox.podAnnotations" (list . "deployment" "central-db") | nindent 8 }} + spec: + {{- if ._rox.central.db._nodeSelector }} + nodeSelector: + {{- ._rox.central.db._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.central.db.tolerations }} + tolerations: + {{- toYaml ._rox.central.db.tolerations | nindent 8 }} + {{- end }} + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Central-db is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + serviceAccountName: central-db + terminationGracePeriodSeconds: 120 + initContainers: + - name: init-db + image: {{ ._rox.central.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + command: + - init-entrypoint.sh + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: central-db-password + mountPath: /run/secrets/stackrox.io/secrets + resources: + {{- ._rox.central.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + containers: + - name: central-db + image: {{ ._rox.central.db.image.fullRef | quote }} + env: + - name: POSTGRES_HOST_AUTH_METHOD + value: "password" + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + ports: + - containerPort: 5432 + name: postgresql + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -c + - -e + - | + exec pg_isready -U "postgres" -h 127.0.0.1 -p 5432 + failureThreshold: 3 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + {{- ._rox.central.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + volumeMounts: + - name: config-volume + mountPath: /etc/stackrox.d/config/ + - mountPath: /var/lib/postgresql/data + name: disk + - name: central-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + - mountPath: /dev/shm + name: shared-memory + securityContext: + fsGroup: 70 + volumes: + - name: disk + {{- toYaml ._rox.central.db.persistence._volumeCfg | nindent 8 }} + - name: config-volume + configMap: + name: {{ default "central-db-config" ._rox.central.db.configOverride }} + - name: central-db-password + secret: + secretName: central-db-password + - name: central-db-tls-volume + secret: + secretName: central-db-tls + defaultMode: 0640 + items: + - key: cert.pem + path: server.crt + - key: key.pem + path: server.key + - key: ca.pem + path: root.crt + - name: shared-memory + emptyDir: + medium: Memory + {{- /* Keep this in sync with shared_buffers in config/centraldb/postgresql.conf */}} + sizeLimit: 2Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: central-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "central-db") | nindent 4 }} +spec: + ports: + - name: tcp-db + port: 5432 + protocol: TCP + targetPort: postgresql + selector: + app: central-db + type: ClusterIP +{{- end }} +{{- if ._rox.central.db._password }} +{{- if not (kindIs "invalid" ._rox.central.db._password.value) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: central-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.central.db._password.value | nindent 4 }} +{{- end }} +{{- end }} diff --git a/4.3.8/central-services/templates/01-central-13-deployment.yaml b/4.3.8/central-services/templates/01-central-13-deployment.yaml new file mode 100644 index 0000000..f56a974 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-13-deployment.yaml @@ -0,0 +1,271 @@ +{{- include "srox.init" . -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: central + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "deployment" "central") | nindent 4 }} + app: central + annotations: + {{- include "srox.annotations" (list . "deployment" "central") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: central + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: central + {{- include "srox.podLabels" (list . "deployment" "central") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8443" + {{- include "srox.podAnnotations" (list . "deployment" "central") | nindent 8 }} + spec: + {{- if ._rox.central._nodeSelector }} + nodeSelector: + {{- ._rox.central._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.central.tolerations }} + tolerations: + {{- toYaml ._rox.central.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.central.affinity | nindent 8 }} + serviceAccountName: central + securityContext: + fsGroup: 4000 + runAsUser: 4000 + containers: + - name: central + image: {{ ._rox.central.image.fullRef | quote }} + command: + - /stackrox/central-entrypoint.sh + ports: + {{- toYaml ._rox.central._containerPorts | nindent 10 }} + readinessProbe: + httpGet: + scheme: HTTPS + path: /v1/ping + port: 8443 + resources: + {{- ._rox.central._resources | nindent 10 }} + securityContext: + capabilities: + drop: ["NET_RAW"] + readOnlyRootFilesystem: true + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if ne (._rox.central.telemetry.enabled | toString) "false" }} + {{- if ._rox.central.telemetry.storage.endpoint }} + - name: ROX_TELEMETRY_ENDPOINT + value: {{ ._rox.central.telemetry.storage.endpoint | quote }} + {{- end }} + {{- if ._rox.central.telemetry.storage.key }} + - name: ROX_TELEMETRY_STORAGE_KEY_V1 + value: {{ ._rox.central.telemetry.storage.key | quote }} + {{- end }} + {{- end }} + - name: ROX_OFFLINE_MODE + value: {{ ._rox.env.offlineMode | quote }} + {{- if and (eq ._rox.env.openshift 4) (not ._rox.env.managedServices) }} + - name: ROX_ENABLE_OPENSHIFT_AUTH + value: "true" + {{- end }} + {{- if ._rox.env.openshift }} + - name: ROX_OPENSHIFT + value: "true" + {{- end }} + {{- if ._rox.env.managedServices }} + - name: ROX_MANAGED_CENTRAL + value: "true" + - name: ROX_ENABLE_CENTRAL_DIAGNOSTICS + value: "false" + - name: ROX_ENABLE_KERNEL_PACKAGE_UPLOAD + value: "false" + - name: ROX_TENANT_ID + valueFrom: + fieldRef: + fieldPath: metadata.labels['rhacs.redhat.com/tenant'] + {{- end }} + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: ROX_ENC_NOTIFIER_CREDS + value: "true" + {{- end }} + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + {{- end }} + - name: ROX_INSTALL_METHOD + value: {{ ._rox.env.installMethod | quote }} + {{- include "srox.envVars" (list . "deployment" "central" "central") | nindent 8 }} + volumeMounts: + - name: varlog + mountPath: /var/log/stackrox/ + - name: central-tmp-volume + mountPath: /tmp + - name: central-etc-ssl-volume + mountPath: /etc/ssl + - name: central-etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: central-certs-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: central-default-tls-cert-volume + mountPath: /run/secrets/stackrox.io/default-tls-cert/ + readOnly: true + - name: central-htpasswd-volume + mountPath: /run/secrets/stackrox.io/htpasswd/ + readOnly: true + - name: central-jwt-volume + mountPath: /run/secrets/stackrox.io/jwt/ + readOnly: true + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: central-license-volume + mountPath: /run/secrets/stackrox.io/central-license/ + readOnly: true + - name: stackrox-db + mountPath: /var/lib/stackrox + - name: central-config-volume + mountPath: /etc/stackrox + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: endpoints-config-volume + mountPath: /etc/stackrox.d/endpoints/ + readOnly: true + - name: central-db-password + mountPath: /run/secrets/stackrox.io/db-password + - name: central-external-db-volume + mountPath: /etc/ext-db + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: central-encryption-key + mountPath: /run/secrets/stackrox.io/central-encryption-key + {{- end }} + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + {{- range $extraMount := (default list ._rox.central.extraMounts) }} + - name: {{ $extraMount.name }} + {{- $extraMount.mount | toYaml | nindent 10 }} + {{- end }} + {{- range $mount := (default list ._rox.central.declarativeConfiguration.mounts.configMaps) }} + - name: {{ $mount }} + mountPath: /run/stackrox.io/declarative-configuration/{{ $mount }} + readOnly: true + {{- end }} + {{- range $mount := (default list ._rox.central.declarativeConfiguration.mounts.secrets) }} + - name: {{ $mount }} + mountPath: /run/stackrox.io/declarative-configuration/{{ $mount }} + readOnly: true + {{- end }} + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + volumes: + - name: varlog + emptyDir: {} + - name: central-tmp-volume + emptyDir: {} + - name: central-etc-ssl-volume + emptyDir: {} + - name: central-etc-pki-volume + emptyDir: {} + - name: central-certs-volume + secret: + secretName: central-tls + - name: central-default-tls-cert-volume + secret: + secretName: {{ default "central-default-tls-cert" ._rox.central.defaultTLS.reference }} + optional: true + - name: central-htpasswd-volume + secret: + secretName: central-htpasswd + optional: true + - name: central-jwt-volume + secret: + secretName: central-tls + items: + - key: jwt-key.pem + path: jwt-key.pem + - name: additional-ca-volume + secret: + secretName: additional-ca + optional: true + - name: central-license-volume + secret: + secretName: central-license + optional: true + - name: central-config-volume + configMap: + name: central-config + optional: true + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: endpoints-config-volume + configMap: + name: central-endpoints + - name: central-db-password + secret: + secretName: central-db-password + - name: central-external-db-volume + configMap: + name: central-external-db + optional: true + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: central-encryption-key + secret: + secretName: central-encryption-key + {{- end }} + {{- end }} + - name: stackrox-db + {{- toYaml ._rox.central.persistence._volumeCfg | nindent 8 }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: central-monitoring-tls + optional: true + {{- end }} + {{- range $extraMount := (default list ._rox.central.extraMounts) }} + - name: {{ $extraMount.name }} + {{- $extraMount.source | toYaml | nindent 8 }} + {{- end }} + {{- range $mount := (default list ._rox.central.declarativeConfiguration.mounts.configMaps) }} + - name: {{ $mount }} + configMap: + name: {{ $mount }} + optional: true + {{- end }} + {{- range $mount := (default list ._rox.central.declarativeConfiguration.mounts.secrets) }} + - name: {{ $mount }} + secret: + secretName: {{ $mount }} + optional: true + {{- end }} + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} diff --git a/4.3.8/central-services/templates/01-central-14-service.yaml b/4.3.8/central-services/templates/01-central-14-service.yaml new file mode 100644 index 0000000..f459fd7 --- /dev/null +++ b/4.3.8/central-services/templates/01-central-14-service.yaml @@ -0,0 +1,43 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: Service +metadata: + name: central + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "central") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: central-monitoring-tls + {{- end }} +spec: + ports: + {{- toYaml ._rox.central._servicePorts | nindent 4 }} + selector: + app: central + type: ClusterIP + +{{ if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: central-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "central-internal-no-istio-mtls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "destinationrule" "central-internal-no-istio-mtls") | nindent 4 }} + stackrox.io/description: "Disable Istio mTLS for port 443, since StackRox services use built-in mTLS." +spec: + host: central.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 443 + tls: + mode: DISABLE +{{ end }} diff --git a/4.3.8/central-services/templates/01-central-15-exposure.yaml b/4.3.8/central-services/templates/01-central-15-exposure.yaml new file mode 100644 index 0000000..9bfdbbb --- /dev/null +++ b/4.3.8/central-services/templates/01-central-15-exposure.yaml @@ -0,0 +1,95 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.central.exposure.route.enabled }} +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: central + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "route" "central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "route" "central") | nindent 4 }} +spec: +{{- if ._rox.central.exposure.route.host }} + host: {{ ._rox.central.exposure.route.host }} +{{- end }} + port: + targetPort: https + tls: + termination: passthrough + to: + kind: Service + name: central +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: central-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "route" "central-mtls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "route" "central-mtls") | nindent 4 }} +spec: + host: "central.{{ .Release.Namespace }}" + port: + targetPort: https + tls: + termination: passthrough + to: + kind: Service + name: central +--- +{{- end }} + +{{- if ._rox.central.exposure.nodePort.enabled }} +apiVersion: v1 +kind: Service +metadata: + annotations: + {{- include "srox.annotations" (list . "service" "central-loadbalancer") | nindent 4 }} + cloud.google.com/app-protocols: '{"api": "HTTPS"}' + service.alpha.kubernetes.io/app-protocols: '{"api": "HTTPS"}' + name: central-loadbalancer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "central-loadbalancer") | nindent 4 }} +spec: + type: NodePort + ports: + - port: 443 + targetPort: api +{{- if ._rox.central.exposure.nodePort.port }} + nodePort: {{ ._rox.central.exposure.nodePort.port }} +{{- end }} + selector: + app: central +--- +{{- end }} + +{{- if ._rox.central.exposure.loadBalancer.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: central-loadbalancer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "central-loadbalancer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "central-loadbalancer") | nindent 4 }} +spec: + type: LoadBalancer + # This ensures that the client source IP is retained for audit logging purposes. + # Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + externalTrafficPolicy: Local + ports: + - port: {{ ._rox.central.exposure.loadBalancer.port }} + targetPort: api + selector: + app: central +{{- if ._rox.central.exposure.loadBalancer.ip }} + loadBalancerIP: {{ ._rox.central.exposure.loadBalancer.ip }} +{{- end }} +--- +{{- end}} diff --git a/4.3.8/central-services/templates/02-scanner-00-serviceaccount.yaml b/4.3.8/central-services/templates/02-scanner-00-serviceaccount.yaml new file mode 100644 index 0000000..a27c602 --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-00-serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "scanner") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} + +{{ end -}} diff --git a/4.3.8/central-services/templates/02-scanner-01-psps.yaml b/4.3.8/central-services/templates/02-scanner-01-psps.yaml new file mode 100644 index 0000000..23b398c --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-01-psps.yaml @@ -0,0 +1,69 @@ +{{- include "srox.init" . -}} + +{{- if and (not ._rox.scanner.disable) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-scanner-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-scanner-psp") | nindent 4 }} +rules: +- apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-scanner-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-scanner-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-scanner-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-psp") }} +subjects: + - kind: ServiceAccount + name: scanner + namespace: {{ .Release.Namespace }} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-scanner") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' +{{- end }} diff --git a/4.3.8/central-services/templates/02-scanner-01-security.yaml b/4.3.8/central-services/templates/02-scanner-01-security.yaml new file mode 100644 index 0000000..3c1d92b --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-01-security.yaml @@ -0,0 +1,78 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable }} +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-scanner") | nindent 4 }} + kubernetes.io/description: stackrox-scanner is the security constraint for the Scanner container +priority: 0 +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +users: + - system:serviceaccount:{{ .Release.Namespace }}:scanner +volumes: + - '*' +allowHostDirVolumePlugin: false +allowedCapabilities: [] +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +defaultAddCapabilities: [] +fsGroup: + type: RunAsAny +readOnlyRootFilesystem: false +requiredDropCapabilities: [] + +{{- else if eq ._rox.env.openshift 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-scanner-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-scanner-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-scanner-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - anyuid + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: scanner-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "scanner-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "scanner-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-scanner-scc +subjects: +- kind: ServiceAccount + name: scanner + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} diff --git a/4.3.8/central-services/templates/02-scanner-02-db-password-secret.yaml b/4.3.8/central-services/templates/02-scanner-02-db-password-secret.yaml new file mode 100644 index 0000000..c6c0bc1 --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-02-db-password-secret.yaml @@ -0,0 +1,27 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if ._rox.scanner._dbPassword -}} +{{- if not (kindIs "invalid" ._rox.scanner._dbPassword.value) -}} + +apiVersion: v1 +kind: Secret +metadata: + name: scanner-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.scanner._dbPassword.value | nindent 4 }} + +{{- end -}} +{{- end -}} + +{{ end -}} diff --git a/4.3.8/central-services/templates/02-scanner-03-tls-secret.yaml b/4.3.8/central-services/templates/02-scanner-03-tls-secret.yaml new file mode 100644 index 0000000..7c590ff --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-03-tls-secret.yaml @@ -0,0 +1,55 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if and ._rox.scanner._serviceTLS ._rox._ca -}} + +apiVersion: v1 +kind: Secret +metadata: + name: scanner-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + ca.pem: | + {{- ._rox._ca.Cert | nindent 4 }} + cert.pem: | + {{- ._rox.scanner._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scanner._serviceTLS.Key | nindent 4 }} + +--- + +{{- end }} + +{{ if and ._rox.scanner._dbServiceTLS ._rox._ca -}} + +apiVersion: v1 +kind: Secret +metadata: + name: scanner-db-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-db-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-db-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox._ca.Cert | nindent 4 }} + cert.pem: | + {{- ._rox.scanner._dbServiceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scanner._dbServiceTLS.Key | nindent 4 }} + +{{- end -}} + +{{ end -}} diff --git a/4.3.8/central-services/templates/02-scanner-04-scanner-config.yaml b/4.3.8/central-services/templates/02-scanner-04-scanner-config.yaml new file mode 100644 index 0000000..4ed16c7 --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-04-scanner-config.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner/config.yaml.tpl") . | nindent 4 }} + +{{ end -}} diff --git a/4.3.8/central-services/templates/02-scanner-05-network-policy.yaml b/4.3.8/central-services/templates/02-scanner-05-network-policy.yaml new file mode 100644 index 0000000..99f7233 --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-05-network-policy.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner + ingress: + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP +{{ if or (eq ._rox.scanner.mode "slim") ._rox.env.openshift }} + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP +{{ end }} + policyTypes: + - Ingress + +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-db") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-db + ingress: + - from: + - podSelector: + matchLabels: + app: scanner + ports: + - port: 5432 + protocol: TCP + policyTypes: + - Ingress + +{{ end -}} + +{{ if ._rox.scanner.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: scanner + policyTypes: + - Ingress +{{ end }} diff --git a/4.3.8/central-services/templates/02-scanner-06-deployment.yaml b/4.3.8/central-services/templates/02-scanner-06-deployment.yaml new file mode 100644 index 0000000..89ac82c --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-06-deployment.yaml @@ -0,0 +1,296 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + app: scanner + {{- include "srox.labels" (list . "deployment" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner") | nindent 4 }} +spec: + replicas: {{ ._rox.scanner.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner + {{- include "srox.podLabels" (list . "deployment" "scanner") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8080,8443" + {{- include "srox.podAnnotations" (list . "deployment" "scanner") | nindent 8 }} + spec: + {{- if ._rox.scanner._nodeSelector }} + nodeSelector: + {{- ._rox.scanner._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.tolerations }} + tolerations: + {{- toYaml ._rox.scanner.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scanner.affinity | nindent 8 }} + containers: + - name: scanner + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimImage.fullRef | quote }} + {{ else }} + image: {{ ._rox.scanner.image.fullRef | quote }} + {{ end -}} + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if ._rox.env.openshift }} + - name: ROX_OPENSHIFT_API + value: "true" + {{- end}} + {{- include "srox.envVars" (list . "deployment" "scanner" "scanner") | nindent 8 }} + resources: + {{- ._rox.scanner._resources | nindent 10 }} + command: + - /entrypoint.sh + ports: + - name: https + containerPort: 8080 + - name: grpc + containerPort: 8443 + {{ if ._rox.scanner.exposeMonitoring -}} + - name: monitoring + containerPort: 9090 + {{- end}} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /scanner/ping + port: 8080 + timeoutSeconds: 10 + periodSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + volumeMounts: + - name: scanner-etc-ssl-volume + mountPath: /etc/ssl + - name: scanner-etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: scanner-config-volume + mountPath: /etc/scanner + readOnly: true + - name: scanner-tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: vuln-temp-db + mountPath: /var/lib/stackrox + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: scanner-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner + volumes: + - name: additional-ca-volume + secret: + defaultMode: 420 + optional: true + secretName: additional-ca + - name: scanner-etc-ssl-volume + emptyDir: {} + - name: scanner-etc-pki-volume + emptyDir: {} + - name: scanner-config-volume + configMap: + name: scanner-config + - name: scanner-tls-volume + secret: + secretName: scanner-tls + - name: vuln-temp-db + emptyDir: {} + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: scanner-db-password + secret: + secretName: scanner-db-password + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + app: scanner-db + {{- include "srox.labels" (list . "deployment" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-db + {{- include "srox.podLabels" (list . "deployment" "scanner-db") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "5432" + {{- include "srox.podAnnotations" (list . "deployment" "scanner-db") | nindent 8 }} + spec: + {{- if ._rox.scanner._dbNodeSelector }} + nodeSelector: + {{- ._rox.scanner._dbNodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.dbTolerations }} + tolerations: + {{- toYaml ._rox.scanner.dbTolerations | nindent 8 }} + {{- end }} + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # ScannerDB is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + initContainers: + - name: init-db + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimDBImage.fullRef | quote }} + {{ else -}} + image: {{ ._rox.scanner.dbImage.fullRef | quote }} + {{ end -}} + env: + - name: POSTGRES_PASSWORD_FILE + value: "/run/secrets/stackrox.io/secrets/password" + - name: ROX_SCANNER_DB_INIT + value: "true" + resources: + {{- ._rox.scanner._dbResources | nindent 12 }} + volumeMounts: + - name: scanner-db-data + mountPath: /var/lib/postgresql/data + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + readOnly: true + - name: scanner-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + containers: + - name: db + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimDBImage.fullRef | quote }} + {{ else -}} + image: {{ ._rox.scanner.dbImage.fullRef | quote }} + {{ end -}} + env: + {{- include "srox.envVars" (list . "deployment" "scanner-db" "db") | nindent 10 }} + ports: + - name: tcp-postgresql + protocol: TCP + containerPort: 5432 + resources: + {{- ._rox.scanner._dbResources | nindent 10 }} + volumeMounts: + - name: scanner-db-data + mountPath: /var/lib/postgresql/data + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + readOnly: true + serviceAccountName: scanner + securityContext: + fsGroup: 70 + runAsGroup: 70 + runAsNonRoot: true + runAsUser: 70 + volumes: + - name: scanner-config-volume + configMap: + name: scanner-config + - name: scanner-tls-volume + secret: + secretName: scanner-tls + - name: scanner-db-tls-volume + secret: + secretName: scanner-db-tls + defaultMode: 0640 + items: + - key: cert.pem + path: server.crt + - key: key.pem + path: server.key + - key: ca.pem + path: root.crt + - name: scanner-db-data + emptyDir: {} + - name: scanner-db-password + secret: + secretName: scanner-db-password + +{{ end -}} diff --git a/4.3.8/central-services/templates/02-scanner-07-service.yaml b/4.3.8/central-services/templates/02-scanner-07-service.yaml new file mode 100644 index 0000000..2f65b15 --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-07-service.yaml @@ -0,0 +1,99 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: Service +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner") | nindent 4 }} +spec: + ports: + - name: https-scanner + port: 8080 + targetPort: 8080 + - name: grpcs-scanner + port: 8443 + targetPort: 8443 + {{ if ._rox.scanner.exposeMonitoring -}} + - name: monitoring + port: 9090 + targetPort: monitoring + {{- end}} + selector: + app: scanner + type: ClusterIP + +--- + +apiVersion: v1 +kind: Service +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-db") | nindent 4 }} +spec: + ports: + - name: tcp-db + port: 5432 + targetPort: 5432 + selector: + app: scanner-db + type: ClusterIP + +{{ if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for ports 8080 and 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8080 + tls: + mode: DISABLE + - port: + number: 8443 + tls: + mode: DISABLE + +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-db-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-db-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 5432, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-db-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-db.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 5432 + tls: + mode: DISABLE +{{ end }} + +{{ end -}} diff --git a/4.3.8/central-services/templates/02-scanner-08-hpa.yaml b/4.3.8/central-services/templates/02-scanner-08-hpa.yaml new file mode 100644 index 0000000..c7af476 --- /dev/null +++ b/4.3.8/central-services/templates/02-scanner-08-hpa.yaml @@ -0,0 +1,25 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if not ._rox.scanner.autoscaling.disable -}} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scanner.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scanner.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner + targetCPUUtilizationPercentage: 150 +{{ end -}} + +{{ end -}} diff --git a/4.3.8/central-services/templates/99-generated-values-secret.yaml b/4.3.8/central-services/templates/99-generated-values-secret.yaml new file mode 100644 index 0000000..b3499e8 --- /dev/null +++ b/4.3.8/central-services/templates/99-generated-values-secret.yaml @@ -0,0 +1,25 @@ +{{- include "srox.init" . -}} + +{{- if ._rox._state.generated -}} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ ._rox._state.generatedName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "generated-helm-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "generated-helm-config") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" + "helm.sh/hook-delete-policy": "never" +stringData: + generated-values.yaml: | + # The following values were generated by the StackRox Central Services Helm chart. + # You can pass this file to `helm install` via the `-f` parameter, which in conjunction + # with your local values files and values specified via `--set` will allow you to + # deterministically reproduce the deployment. + {{- ._rox._state.generated | toYaml | nindent 4 }} + +{{- end -}} diff --git a/4.3.8/central-services/templates/99-openshift-monitoring.yaml b/4.3.8/central-services/templates/99-openshift-monitoring.yaml new file mode 100644 index 0000000..e9c512e --- /dev/null +++ b/4.3.8/central-services/templates/99-openshift-monitoring.yaml @@ -0,0 +1,134 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.monitoring ._rox.monitoring.openshift ._rox.monitoring.openshift.enabled -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: central-prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "central-prometheus-k8s") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "central-prometheus-k8s") | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: central-prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "central-prometheus-k8s") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "central-prometheus-k8s") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: central-prometheus-k8s +subjects: +- kind: ServiceAccount + name: prometheus-k8s + namespace: openshift-monitoring + +--- + +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: "central-monitor-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "servicemonitor" (print "central-monitor-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "servicemonitor" (print "central-monitor-" .Release.Namespace)) | nindent 4 }} +spec: + endpoints: + - interval: 30s + path: metrics + port: monitoring-tls + scheme: https + tlsConfig: + caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt + certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt + keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key + serverName: "central.{{ .Release.Namespace }}.svc" + selector: + matchLabels: + app.kubernetes.io/component: central + namespaceSelector: + matchNames: + - "{{ .Release.Namespace }}" + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "rhacs-central-auth-reader-{{ .Release.Namespace }}" + namespace: kube-system + labels: + {{- include "srox.labels" (list . "rolebinding" (print "rhacs-central-auth-reader-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" (print "rhacs-central-auth-reader-" .Release.Namespace)) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: central + namespace: "{{ .Release.Namespace }}" + +--- + +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: "central-telemeter-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "prometheusrule" (print "central-telemeter-" .Release.Namespace )) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "prometheusrule" (print "central-telemeter-" .Release.Namespace )) | nindent 4 }} +spec: + groups: + - name: rhacs.telemeter + rules: + - expr: | + max by (build, central_id, central_version, hosting, install_method) ( + rox_central_info{branding="RHACS"} + ) + record: rhacs:telemetry:rox_central_info + + - expr: | + max by (central_id) ( + rox_central_secured_clusters{branding="RHACS"} + ) + record: rhacs:telemetry:rox_central_secured_clusters + + - expr: | + max by (central_id) ( + rox_central_secured_nodes{branding="RHACS"} + ) + record: rhacs:telemetry:rox_central_secured_nodes + + - expr: | + max by (central_id) ( + rox_central_secured_vcpus{branding="RHACS"} + ) + record: rhacs:telemetry:rox_central_secured_vcpus + +{{- end -}} diff --git a/4.3.8/central-services/templates/NOTES.txt b/4.3.8/central-services/templates/NOTES.txt new file mode 100644 index 0000000..27922b2 --- /dev/null +++ b/4.3.8/central-services/templates/NOTES.txt @@ -0,0 +1,56 @@ +{{- $_ := include "srox.init" . -}} + +StackRox {{.Chart.AppVersion}} has been installed. + + +{{ if include "srox.checkGenerated" (list . "central.adminPassword.value") -}} +An administrator password has been generated automatically. Use username 'admin' and the following +password to log in for initial setup: + + {{ ._rox.central._adminPassword.value }} + +{{ end -}} + +{{ if ._rox._state.notes -}} +Please take note of the following: +{{ range ._rox._state.notes }} +- {{ . | wrapWith 98 "\n " -}} +{{ end }} + +{{ end -}} + +{{ if ._rox._state.generated -}} +One or several values were automatically generated by Helm. In order to reproduce this deployment +in the future, you can export these values by running + + $ kubectl -n {{ .Release.Namespace }} get secret {{ ._rox._state.generatedName }} \ + -o go-template='{{ `{{ index .data "generated-values.yaml" }}` }}' | \ + base64 --decode >generated-values.yaml + +This file might contain sensitive data, so store it in a safe place. + +{{ end -}} + +{{ if ._rox._state.warnings -}} +When installing StackRox, the following warnings were encountered: +{{ range ._rox._state.warnings }} +- WARNING: {{ . | wrapWith 98 "\n " -}} +{{ end }} + +{{ end -}} + +{{ if ._rox.env.openshift -}} +IMPORTANT: You have deployed into an OpenShift-enabled cluster. If you see that your pods + are not scheduling, run + + oc annotate namespace/{{ .Release.Namespace }} --overwrite openshift.io/node-selector="" +{{ end -}} + + +{{ if ne (._rox.central.telemetry.enabled | toString) "false" }} +StackRox Kubernetes Security Platform collects and transmits anonymous usage and +system configuration information. If you want to OPT OUT from this, use +--set central.telemetry.enabled=false. +{{ end }} + +Thank you for using StackRox! diff --git a/4.3.8/central-services/templates/_central_endpoints.tpl b/4.3.8/central-services/templates/_central_endpoints.tpl new file mode 100644 index 0000000..3bde7d4 --- /dev/null +++ b/4.3.8/central-services/templates/_central_endpoints.tpl @@ -0,0 +1,59 @@ +{{ define "srox.configureCentralEndpoints" }} +{{ $central := . }} +{{ $containerPorts := list (dict "name" "api" "containerPort" 8443) }} +{{ $netPolIngressRules := list (dict "ports" (list (dict "port" 8443 "protocol" "TCP"))) }} +{{ $servicePorts := list (dict "name" "https" "targetPort" "api" "port" 443) }} +{{ $cfgDict := fromYaml $central._endpointsConfig }} +{{ if kindIs "map" $cfgDict }} + {{ if $cfgDict.disableDefault }} + {{ $containerPorts = list }} + {{ $netPolIngressRules = list }} + {{ $servicePorts = list }} + {{ end }} + {{ range $epCfg := default list $cfgDict.endpoints }} + {{ if and $epCfg.listen (kindIs "string" $epCfg.listen) }} + {{ $listenParts := splitList ":" $epCfg.listen }} + {{ if $listenParts }} + {{ $port := last $listenParts }} + {{ if $port }} + {{ if regexMatch "[0-9]+" $port }} + {{ $port = int $port }} + {{ end }} + {{ $containerPort := dict "containerPort" $port }} + {{ if and $epCfg.name (kindIs "string" $epCfg.name) }} + {{ $_ := set $containerPort "name" $epCfg.name }} + {{ end }} + {{ $containerPorts = append $containerPorts $containerPort }} + {{ if $epCfg.servicePort }} + {{ $servicePort := dict "targetPort" $port "port" $epCfg.servicePort }} + {{ if $containerPort.name }} + {{ $_ := set $servicePort "name" $containerPort.name }} + {{ end }} + {{ $servicePorts = append $servicePorts $servicePort }} + {{ end }} + {{ if not (kindIs "invalid" $epCfg.allowIngressFrom) }} + {{ $fromList := $epCfg.allowIngressFrom }} + {{ if not (kindIs "slice" $fromList) }} + {{ $fromList = list $fromList }} + {{ end }} + {{ $netPolIngressRule := dict "ports" (list (dict "port" $port "protocol" "TCP")) "from" $fromList }} + {{ $netPolIngressRules = append $netPolIngressRules $netPolIngressRule }} + {{ end }} + {{ end }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ if $central.exposeMonitoring }} + {{ $containerPorts = append $containerPorts (dict "name" "monitoring" "containerPort" 9090) }} + {{ $servicePorts = append $servicePorts (dict "name" "monitoring" "targetPort" "monitoring" "port" 9090) }} +{{ end }} +# The (...) safe-guard against nil pointer evaluations for Helm versions built with Go < 1.18. +{{ if ((($central.monitoring).openshift).enabled) }} + {{ $containerPorts = append $containerPorts (dict "name" "monitoring-tls" "containerPort" 9091) }} + {{ $servicePorts = append $servicePorts (dict "name" "monitoring-tls" "targetPort" "monitoring-tls" "port" 9091) }} +{{ end }} +{{ $_ := set $central "_containerPorts" $containerPorts }} +{{ $_ = set $central "_servicePorts" $servicePorts }} +{{ $_ = set $central "_netPolIngressRules" $netPolIngressRules }} +{{ end }} diff --git a/4.3.8/central-services/templates/_central_setup.tpl b/4.3.8/central-services/templates/_central_setup.tpl new file mode 100644 index 0000000..6584ad1 --- /dev/null +++ b/4.3.8/central-services/templates/_central_setup.tpl @@ -0,0 +1,140 @@ +{{/* + srox.centralSetup $ + + Configures and initializes central specific values like certificates, admin password or persistence. + */}} +{{ define "srox.centralSetup" }} +{{ $ := . }} +{{ $env := $._rox.env }} +{{ $_ := set $ "_rox" $._rox }} +{{ $centralCfg := $._rox.central }} +{{ $centralDBCfg := $._rox.central.db }} + +{{/* Image settings */}} +{{ include "srox.configureImage" (list $ $centralCfg.image) }} + +{{/* Admin password */}} +{{ include "srox.configurePassword" (list $ "central.adminPassword" "admin") }} + +{{/* Service TLS Certificates */}} +{{ $centralCertSpec := dict "CN" "CENTRAL_SERVICE: Central" "dnsBase" "central" }} +{{ include "srox.configureCrypto" (list $ "central.serviceTLS" $centralCertSpec) }} + +{{/* JWT Token Signer */}} +{{ $jwtSignerSpec := dict "keyOnly" "rsa" }} +{{ include "srox.configureCrypto" (list $ "central.jwtSigner" $jwtSignerSpec) }} + +{{/* Setup Default TLS Certificate. */}} +{{ if $._rox.central.defaultTLS }} + {{ $cert := $._rox.central.defaultTLS._cert }} + {{ $key := $._rox.central.defaultTLS._key }} + {{ if and $cert $key }} + {{ $defaultTLSCert := dict "Cert" $cert "Key" $key }} + {{ $_ := set $._rox.central "_defaultTLS" $defaultTLSCert }} + {{ include "srox.note" (list $ "Configured default TLS certificate") }} + {{ else if or $cert $key }} + {{ include "srox.fail" "Must specify either none or both of central.defaultTLS.cert and central.defaultTLS.key" }} + {{ end }} +{{ end }} + +{{/* Central DB password */}} +{{/* Always set up the password for Postgres if it is enabled */}} +{{ include "srox.configurePassword" (list $ "central.db.password") }} +{{ if not $centralDBCfg.external }} +{{ include "srox.configureImage" (list $ $centralDBCfg.image) }} + +{{/* Central DB Service TLS Certificates */}} +{{ $centralDBCertSpec := dict "CN" "CENTRAL_DB_SERVICE: Central DB" "dnsBase" "central-db" }} +{{ include "srox.configureCrypto" (list $ "central.db.serviceTLS" $centralDBCertSpec) }} +{{ end }} + +{{/* + Setup configuration for persistence backend. + TODO(ROX-16253): Remove PVC + */}} +{{ $volumeCfg := dict }} +{{ if $centralCfg.persistence.none }} + {{ $_ := set $volumeCfg "emptyDir" dict }} +{{ end }} +{{ if $centralCfg.persistence.hostPath }} + {{ if not $centralCfg.nodeSelector }} + {{ include "srox.warn" (list $ "You have selected host path persistence, but not specified a node selector. This is unlikely to work reliably.") }} + {{ end }} + {{ $_ := set $volumeCfg "hostPath" (dict "path" $centralCfg.persistence.hostPath) }} +{{ end }} +{{/* Configure PVC if either any of the settings in `central.persistence.persistentVolumeClaim` are provided, + or no other persistence backend has been configured yet. */}} +{{ if or (not (deepEqual $._rox._configShape.central.persistence.persistentVolumeClaim $centralCfg.persistence.persistentVolumeClaim)) (not $volumeCfg) }} + {{ $pvcCfg := $centralCfg.persistence.persistentVolumeClaim }} + {{ $_ := include "srox.mergeInto" (list $pvcCfg $._rox._defaults.pvcDefaults (dict "createClaim" $.Release.IsInstall)) }} + {{ $_ = set $volumeCfg "persistentVolumeClaim" (dict "claimName" $pvcCfg.claimName) }} + {{ if $pvcCfg.createClaim }} + {{ $_ = set $centralCfg.persistence "_pvcCfg" $pvcCfg }} + {{ end }} +{{ end }} + +{{/* + Central's DB PVC config setup + */}} +{{ $dbVolumeCfg := dict }} +{{ if not $centralDBCfg.external }} +{{ if $centralDBCfg.persistence.none }} + {{ include "srox.warn" (list $ "You have selected no persistence backend. Every deletion of the StackRox Central DB pod will cause you to lose all your data. This is STRONGLY recommended against.") }} + {{ $_ := set $dbVolumeCfg "emptyDir" dict }} +{{ end }} +{{ if $centralDBCfg.persistence.hostPath }} + {{ if not $centralDBCfg.nodeSelector }} + {{ include "srox.warn" (list $ "You have selected host path persistence, but not specified a node selector. This is unlikely to work reliably.") }} + {{ end }} + {{ $_ := set $dbVolumeCfg "hostPath" (dict "path" $centralDBCfg.persistence.hostPath) }} +{{ end }} +{{/* Configure PVC if either any of the settings in `centralDB.persistence.persistentVolumeClaim` are provided, + or no other persistence backend has been configured yet. */}} +{{ if or (not (deepEqual $._rox._configShape.central.db.persistence.persistentVolumeClaim $centralDBCfg.persistence.persistentVolumeClaim)) (not $dbVolumeCfg) }} + {{ $dbPVCCfg := $centralDBCfg.persistence.persistentVolumeClaim }} + {{ $_ := include "srox.mergeInto" (list $dbPVCCfg $._rox._defaults.dbPVCDefaults (dict "createClaim" (or .Release.IsInstall (eq $._rox._renderMode "centralDBOnly")))) }} + {{ $_ = set $dbVolumeCfg "persistentVolumeClaim" (dict "claimName" $dbPVCCfg.claimName) }} + {{ if $dbPVCCfg.createClaim }} + {{ $_ = set $centralDBCfg.persistence "_pvcCfg" $dbPVCCfg }} + {{ end }} +{{ end }} +{{ end }} + +{{ $allPersistenceMethods := keys $volumeCfg | sortAlpha }} +{{ if ne (len $allPersistenceMethods) 1 }} + {{ include "srox.fail" (printf "Invalid or no persistence configurations for central: [%s]" (join "," $allPersistenceMethods)) }} +{{ end }} +{{ $_ = set $centralCfg.persistence "_volumeCfg" $volumeCfg }} +{{ if not $centralDBCfg.external }} +{{ $_ = set $centralDBCfg.persistence "_volumeCfg" $dbVolumeCfg }} +{{ end }} + +{{/* Endpoint configuration */}} +{{ include "srox.configureCentralEndpoints" $._rox.central }} + +{{/* + Exposure configuration setup & sanity checks. + */}} +{{ if $._rox.central.exposure.loadBalancer.enabled }} + {{ include "srox.note" (list $ (printf "Exposing StackRox Central via LoadBalancer service.")) }} +{{ end }} +{{ if $._rox.central.exposure.nodePort.enabled }} + {{ include "srox.note" (list $ (printf "Exposing StackRox Central via NodePort service.")) }} +{{ end }} +{{ if $._rox.central.exposure.route.enabled }} + {{ if not $env.openshift }} + {{ include "srox.fail" (printf "The exposure method 'Route' is only available on OpenShift clusters.") }} + {{ end }} + {{ include "srox.note" (list $ (printf "Exposing StackRox Central via OpenShift Route https://central.%s." $.Release.Namespace)) }} +{{ end }} + +{{ if not (or $._rox.central.exposure.loadBalancer.enabled $._rox.central.exposure.nodePort.enabled $._rox.central.exposure.route.enabled) }} + {{ include "srox.note" (list $ "Not exposing StackRox Central, it will only be reachable cluster-internally.") }} + {{ include "srox.note" (list $ "To enable exposure via LoadBalancer service, use --set central.exposure.loadBalancer.enabled=true.") }} + {{ include "srox.note" (list $ "To enable exposure via NodePort service, use --set central.exposure.nodePort.enabled=true.") }} + {{ if $env.openshift }} + {{ include "srox.note" (list $ "To enable exposure via an OpenShift Route, use --set central.exposure.route.enabled=true.") }} + {{ end }} + {{ include "srox.note" (list $ (printf "To acccess StackRox Central via a port-forward on your local port 18443, run: kubectl -n %s port-forward svc/central 18443:443." .Release.Namespace)) }} +{{ end }} +{{ end }} diff --git a/4.3.8/central-services/templates/_crypto.tpl b/4.3.8/central-services/templates/_crypto.tpl new file mode 100644 index 0000000..1455288 --- /dev/null +++ b/4.3.8/central-services/templates/_crypto.tpl @@ -0,0 +1,239 @@ +{{/* + srox.configureCrypto $ $cryptoConfigPath $spec + + This helper function configures a private key or certificate (public cert + private key) + config entry, from an input config which is accessed via $cryptoConfigPath relative to + $._rox, which we'll refer to as $inputCfg. $inputCfg is expected to be a dict with at + least `key` and `generate` properties. If `generate` is null, it defaults to either `true` + on installations, and `false` on upgrades. `key` is an expandable string. + The result in either mode is written to a dict $outputCfg under $._rox accessed by the + $cryptoConfigPath, with a '_' prepended to the last path element. E.g., if + $cryptoConfigPath is "a.b.c", the input configuration will be read from $._rox.a.b.c, and + the output configuration will be stored in $._rox.a.b._c. + + Private key-only mode is selected if $spec.keyOnly contains a non-zero string, which specifies + the key algorithm to use. In this mode, if $inputCfg.key expands to a non-empty string, this + string will be copied to the `Key` property of $outputCfg. Otherwise, if $inputCfg.generate + is true (wrt. the above defaulting rules), a key with the algorithm prescribed by $spec.keyOnly + will be generated and stored in the `Key` property of $outputCfg. + + Certificate mode is the default. If $inputCfg.cert and $inputCfg.key expand to non-empty strings, + these strings will be copied to the `Cert` and `Key` properties of $outputCfg. Otherwise, if both + of them expand to empty strings (it is an error if only one of them expands to a non-empty + string), and $inputCfg.generate is true, a certificate and private key are generated with the + following options: + - If $inputCfg.ca is true, generate a CA certificate with common name $inputCfg.CN and a 5 year + validity duration. + - Otherwise, generate a leaf certificate with common name $inputCfg.CN and a 1 year validity + duration. The SANs for this certificate are derived from the base DNS name $inputCfg.dnsBase + according to "srox.computeSANs". + + Whenever certificates and/or private keys were generated, the $._rox._state.generated property + is updated to reflect the generated values, such that merging $._rox._state.generated in to + $.Values would have caused this template to simply use the generated values as-is. E.g., if + $cryptoConfigPath was "a.b.c" and $.Values.a.b.c.cert" and $.Values.a.b.c.key" were both empty, + $._rox._state.generated.a.b.c would be set to be a dict with `cert` and `key` properties of the + generated $outputCfg.Cert and $outputCfg.Key. + + If a certificate or private key was generated, $._rox._state.customCertGen is set to true. + */}} +{{- define "srox.configureCrypto" -}} +{{ $ := index . 0 }} +{{ $cryptoConfigPath := index . 1 }} +{{ $spec := index . 2 }} + +{{/* Resolve $cryptoConfigPath. */}} +{{ $cfg := $._rox }} +{{ $newGenerated := dict }} +{{ $genCfg := $newGenerated }} +{{ $cryptoConfigPathList := splitList "." $cryptoConfigPath }} +{{ range $pathElem := $cryptoConfigPathList }} + {{ $cfg = index $cfg $pathElem }} + {{ $newCfg := dict }} + {{ $_ := set $genCfg $pathElem $newCfg }} + {{ $genCfg = $newCfg }} +{{ end }} + +{{/* Make sure `cert` and `key` are expanded (this should already be the case, but better + safe than sorry. */}} +{{ $certExpandSpec := dict "cert" true "key" true }} +{{ include "srox.expandAll" (list $ $cfg $certExpandSpec $cryptoConfigPathList) }} + +{{ $certPEM := $cfg._cert }} +{{ $keyPEM := $cfg._key }} + +{{ $result := dict }} +{{ if $certPEM }} + {{ $result = dict "Cert" $certPEM "Key" (default "" $keyPEM) }} +{{ else if or $certPEM $keyPEM }} + {{ if and $keyPEM $spec.keyOnly }} + {{ $_ := set $result "Key" $keyPEM }} + {{ else }} + {{ include "srox.fail" (printf "Either none or both of %s.cert and %s.key must be specified" $cryptoConfigPath $cryptoConfigPath) }} + {{ end }} +{{ else }} + {{ $generate := $cfg.generate }} + {{ if kindIs "invalid" $generate }} + {{ $generate = $.Release.IsInstall }} + {{ end }} + {{ if $generate }} + {{ if $spec.ca }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"ca\" (genCA .cn 1825) }}" (dict "Template" $.Template "cn" $spec.CN "out" $out) }} + {{ $result = $out.ca }} + {{ else if $spec.keyOnly }} + {{ $key := tpl "{{ genPrivateKey .algo }}" (dict "Template" $.Template "algo" $spec.keyOnly) }} + {{ $_ := set $genCfg "key" $key }} + {{ $_ = set $result "Key" $key }} + {{ else }} + {{ if not $._rox._ca }} + {{ include "srox.fail" (printf "Tried to generate certificate for %s, but no CA certificate is available." $spec.CN) }} + {{ end }} + {{ $sans := dict }} + {{ include "srox.computeSANs" (list $ $sans $spec.dnsBase) }} + {{ $ca := $._rox._ca }} + {{ if kindIs "map" $ca }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"ca\" (buildCustomCert (b64enc .ca.Cert) (b64enc .ca.Key)) }}" (dict "Template" $.Template "ca" $ca "out" $out) }} + {{ $ca = $out.ca }} + {{ end }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"cert\" (genSignedCert .cn nil .sans 365 .ca) }}" (dict "Template" $.Template "cn" $spec.CN "sans" $sans.result "ca" $ca "out" $out) }} + {{ $result = $out.cert }} + {{ $_ := set $genCfg "cert" $result.Cert }} + {{ $_ = set $genCfg "key" $result.Key }} + {{ end }} + {{ $_ := set $genCfg "key" $result.Key }} + {{ if $result.Cert }} + {{ $_ = set $genCfg "cert" $result.Cert }} + {{ end }} + {{ $_ = set $._rox._state "customCertGen" true }} + {{ end }} +{{ end }} + +{{/* Store output configuration and generated properties */}} +{{ $newCfgRoot := dict }} +{{ $newCfg := $newCfgRoot }} +{{ range $pathElem := initial $cryptoConfigPathList }} + {{ $nextCfg := dict }} + {{ $_ := set $newCfg $pathElem $nextCfg }} + {{ $newCfg = $nextCfg }} +{{ end }} +{{ $_ := set $newCfg (last $cryptoConfigPathList | printf "_%s") $result }} +{{ $_ = include "srox.mergeInto" (list $._rox $newCfgRoot) }} +{{ $_ = include "srox.mergeInto" (list $._rox._state.generated $newGenerated) }} +{{ end }} + + +{{/* + srox.configurePassword $ $pwConfigPath [$htpasswdUser] + + This helper function reads a password configuration (YAML dict with `value` + and `generate` properties) referenced by $pwConfigPath relative to $._rox. It + ensures the dict with the same config path relative to $._rox and prepending an underscore + to the last path element is populated in the following way: + - If the `value` property of the input config is nonzero, set `value` in the result to the + expanded value. + - If the optional $htpasswdUser parameter is specified and the `htpasswd` property of the + input config is nonzero, set `htpasswd` in the result to the expanded value of that + property. + - If none of the above (non-mutually-exclusive) cases apply: + - If `generate` is true OR both `generate` is null and this is an installation, + not an upgrade, generate a random password with 32 alphanumeric characters. + - Otherwise, leave the result property empty. + - If the optional $htpasswdUser parameter was specified AND the `value` property in the + result property was set per the above rules AND the `htpasswd` property was not set, + populate the `htpasswd` property of the result by generating an htpasswd stanza with + the computed `value` as the password and $htpasswdUser as the username. + + The $._rox._state.generated property is adjusted accordingly. + */}} +{{- define "srox.configurePassword" -}} +{{ $ := index . 0 }} +{{ $pwConfigPath := index . 1 }} +{{ $htpasswdUser := "" }} +{{ if gt (len .) 2 }} + {{ $htpasswdUser = index . 2 }} +{{ end }} +{{ $cfg := $._rox }} +{{ $newGenerated := dict }} +{{ $genCfg := $newGenerated }} +{{ $pwConfigPathList := splitList "." $pwConfigPath }} +{{ range $pathElem := $pwConfigPathList }} + {{ $cfg = index $cfg $pathElem }} + {{ $newCfg := dict }} + {{ $_ := set $genCfg $pathElem $newCfg }} + {{ $genCfg = $newCfg }} +{{ end }} + +{{/* Make sure that `value` and `htpasswd` within $cfg are expanded (this should already be the + case but better safe than sorry). */}} +{{ $pwExpandSpec := dict "value" true "htpasswd" true }} +{{ include "srox.expandAll" (list $ $cfg $pwExpandSpec $pwConfigPathList) }} + +{{ $result := dict }} +{{ if and $htpasswdUser (not (kindIs "invalid" $cfg._htpasswd)) }} + {{ $htpasswd := $cfg._htpasswd }} + {{ $_ := set $result "htpasswd" $htpasswd }} +{{ end }} +{{ if not $result.htpasswd }} + {{ $pw := dict.nil }} + {{ if kindIs "invalid" $cfg._value }} + {{ $generate := $cfg.generate }} + {{ if kindIs "invalid" $generate }} + {{ $generate = $.Release.IsInstall }} + {{ end }} + {{ if $generate }} + {{ $pw = randAlphaNum 32 }} + {{ $_ := set $genCfg "value" $pw }} + {{ end }} + {{ else }} + {{ $pw = $cfg._value }} + {{ end }} + {{ if not (kindIs "invalid" $pw) }} + {{ $_ := set $result "value" $pw }} + {{ end }} + {{ if and $htpasswdUser $pw }} + {{ $htpasswd := tpl "{{ htpasswd .user .pw }}" (dict "Template" $.Template "user" $htpasswdUser "pw" $pw) }} + {{ $_ := set $result "htpasswd" $htpasswd }} + {{ end }} +{{ else if $cfg.value }} + {{ include "srox.fail" (printf "Both a htpasswd and a value are specified for %s, this is illegal. Remove the `value` property, or ensure that `htpasswd` is null." $pwConfigPath) }} +{{ end }} +{{ $newCfgRoot := dict }} +{{ $newCfg := $newCfgRoot }} +{{ range $pathElem := initial $pwConfigPathList }} + {{ $nextCfg := dict }} + {{ $_ := set $newCfg $pathElem $nextCfg }} + {{ $newCfg = $nextCfg }} +{{ end }} +{{ $_ := set $newCfg (last $pwConfigPathList | printf "_%s") $result }} +{{ $_ = include "srox.mergeInto" (list $._rox $newCfgRoot) }} +{{ $_ = include "srox.mergeInto" (list $._rox._state.generated $newGenerated) }} +{{ end }} + + +{{/* + srox.computeSANs $ $out $svcName + + Compute the applicable SANs for a service with name $svcName, deployed in namespace + $.Release.Namespace (= $releaseNS). + Generally, SANs following the pattern "$svcName.$releaseNS[.svc[.cluster.local]]" will be + generated. If $releaseNS is not "stackrox", another set of SANs with the same pattern, + but assuming $releaseNS = "stackrox", will be generated in addition. + The result is stored as a list in $out.result. + */}} +{{ define "srox.computeSANs" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ $svcName := index . 2 }} +{{ $releaseNS := $.Release.Namespace }} +{{ $sans := list }} +{{ range $ns := list $releaseNS "stackrox" | uniq | sortAlpha }} + {{ $baseDNS := printf "%s.%s" $svcName $ns }} + {{ range $suffix := tuple "" ".svc" ".svc.cluster.local" }} + {{ $sans = printf "%s%s" $baseDNS $suffix | append $sans }} + {{ end }} +{{ end }} +{{ $_ := set $out "result" $sans }} +{{ end }} diff --git a/4.3.8/central-services/templates/_dict.tpl b/4.3.8/central-services/templates/_dict.tpl new file mode 100644 index 0000000..bf14a6d --- /dev/null +++ b/4.3.8/central-services/templates/_dict.tpl @@ -0,0 +1,142 @@ +{{/* + srox.compactDict $target [$depth] + + Compacts a dict $target by removing entries with empty values. + By default, only the top-level dict $target itself is modified. If the optional $depth + parameter is specified and is non-zero, this determines the recursion depth over which the + compaction is applied to nested diocts as well. A $depth of -1 means to compact all nested + dicts, regardless of depth. + */}} +{{ define "srox.compactDict" }} +{{ $args := . }} +{{ if not (kindIs "slice" $args) }} + {{ $args = list $args 0 }} +{{ end }} +{{ $target := index $args 0 }} +{{ $depth := index $args 1 }} +{{ $zeroValKeys := list }} +{{ range $k, $v := $target }} + {{ if and (kindIs "map" $v) (ne $depth 0) }} + {{ include "srox.compactDict" (list $v (sub $depth 1)) }} + {{ end }} + {{ if not $v }} + {{ $zeroValKeys = append $zeroValKeys $k }} + {{ end }} +{{ end }} +{{ range $k := $zeroValKeys }} + {{ $_ := unset $target $k }} +{{ end }} +{{ end }} + +{{/* + srox.destructiveMergeOverwrite $out $dict1 $dict2... + + Recursively merges $dict1, $dict2 (in this order) into $out, similar to mergeOverwrite. + The eponymous difference is the fact that any explicit "null" entries in the source + dictionaries cause the respective entry to be deleted. + */}} +{{ define "srox.destructiveMergeOverwrite" }} +{{ $out := first . }} +{{ $toMergeList := rest . }} +{{ range $toMerge := $toMergeList }} + {{ range $k, $v := $toMerge }} + {{ if kindIs "invalid" $v }} + {{ $_ := unset $out $k }} + {{ else if kindIs "map" $v }} + {{ $outV := index $out $k }} + {{ if kindIs "invalid" $outV }} + {{ $_ := set $out $k (deepCopy $v) }} + {{ else if kindIs "map" $outV }} + {{ include "srox.destructiveMergeOverwrite" (list $outV $v) }} + {{ else }} + {{ fail (printf "when merging at key %s: incompatible kinds %s and %s" $k (kindOf $v) (kindOf $outV)) }} + {{ end }} + {{ else }} + {{ $_ := set $out $k $v }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox.stringifyDictValues $dict + + Recursively traverses $dict and converts every non-dict value to a string. + */}} +{{ define "srox.stringifyDictValues" }} +{{ $dict := . }} +{{ range $k, $v := $dict }} + {{ if kindIs "map" $v }} + {{ include "srox.stringifyDictValues" $v }} + {{ else }} + {{ $_ := set $dict $k (toString $v) }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox.safeDictLookup $dict $out $path + + Looks up $path in $dict, and stores the result (if any) in $out.result. + $path is a dot-separated list of nested field names. An empty $path causes + $dict to be stored in $out.result. + + Example: srox.safeDictLookup $dict $out "a.b.c" stores the value of $dict.a.b.c, if + it exists, in $out.result. Otherwise, it does nothing - in particular, it does + not fail, as accessing $dict.a.b.c unconditionally would if any of $dict, $dict.a, + or $dict.a.b was not a dict. + */}} +{{ define "srox.safeDictLookup" }} +{{ $dict := index . 0 }} +{{ $out := index . 1 }} +{{ $path := index . 2 }} +{{ $curr := $dict }} +{{ $pathList := splitList "." $path | compact }} +{{ range $pathElem := $pathList }} + {{ if kindIs "map" $curr }} + {{ $curr = index $curr $pathElem }} + {{ else if not (kindIs "invalid" $curr) }} + {{ $curr = dict.nil }} + {{ end }} +{{ end }} +{{ if not (kindIs "invalid" $curr) }} + {{ $_ := set $out "result" $curr }} +{{ end }} +{{ end }} + + + +{{/* + srox.mergeInto $tgt $src1..$srcN + + Recursively merges values from $src1, ..., $srcN into $tgt, giving preference to + values in $tgt. + + Unlike Sprig's merge, this does not overwrite falsy values when explicitly defined, + with the exception of `null` values (this also sets it apart from Sprig's mergeOverwrite). + + Whenever entire (nested) dicts are merged as-is from one of the sources into $tgt, a deep + copy of the respective nested dict is created. + + An empty string is always returned, hence this should be invoked in the form + $_ := include "srox.mergeInto" (list $tgt $src1 $src2) + */}} +{{ define "srox.mergeInto" }} +{{ $tgt := first . }} +{{ range $src := rest . }} + {{ range $k, $srcV := $src }} + {{ $tgtV := index $tgt $k }} + {{ if kindIs "map" $srcV }} + {{ if kindIs "invalid" $tgtV }} + {{ $_ := set $tgt $k (deepCopy $srcV) }} + {{ else if kindIs "map" $tgtV }} + {{ $_ := include "srox.mergeInto" (list $tgtV $srcV) }} + {{ else }} + {{ fail (printf "Incompatible kinds for key %s: %s vs %s" $k (kindOf $srcV) (kindOf $tgtV)) }} + {{ end }} + {{ else if and (not (kindIs "invalid" $srcV)) (kindIs "invalid" $tgtV) }} + {{ $_ := set $tgt $k $srcV }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} diff --git a/4.3.8/central-services/templates/_expand.tpl b/4.3.8/central-services/templates/_expand.tpl new file mode 100644 index 0000000..ed1cb1f --- /dev/null +++ b/4.3.8/central-services/templates/_expand.tpl @@ -0,0 +1,96 @@ +{{/* + srox.expandAll $ $target $expandable [$path] + + Expands values within $target that are flagged in $expandable, using $path + as the path from the configuration root to $target for error reporting purposes. + + If $target is nil, nothing happens. Otherwise, $target must be a dict. For every key + of $target that is also present in $expandable, the following action is performed: + - If the entry in $expandable is a dict, recursive invoke "srox.expandAll" on the + respective entries, with an adjusted $path. + - Otherwise, the entry in $expandable is assume to be of boolean value. If the value is + true, the corresponding entry's value in $target is expanded (see "srox._expandSingle" + below for a definition of expanding), and the result of the expansion is stored under + the key with a "_" prepended in $target. The original entry in $target is removed. This + ensures "srox.expandAll" is an idempotent operation). + */}} +{{ define "srox.expandAll" }} +{{ $args := . }} +{{ $ := index $args 0 }} +{{ $target := index $args 1 }} +{{ $expandable := index $args 2 }} +{{ $path := list }} +{{ if ge (len $args) 4 }} + {{ $path = index $args 3 }} + {{ if kindIs "string" $path }} + {{ $path = splitList "." $path | compact }} + {{ end }} +{{ end }} + +{{ if kindIs "map" $target }} + {{ range $k, $v := $expandable }} + {{ $childPath := append $path $k }} + {{ $targetV := index $target $k }} + {{ if kindIs "map" $v }} + {{ include "srox.expandAll" (list $ $targetV $v $childPath) }} + {{ else if $v }} + {{ if not (kindIs "invalid" $targetV) }} + {{ $expanded := include "srox._expandSingle" (list $ $targetV (join "." $childPath)) }} + {{ $_ := set $target (printf "_%s" $k) $expanded }} + {{ end }} + {{ $_ := unset $target $k }} + {{ end }} + {{ end }} +{{ else if not (kindIs "invalid" $target) }} + {{ include "srox.fail" (printf "Error expanding value at %s: expected map, got: %s" (join "." $path) (kindOf $target)) }} +{{ end }} +{{ end }} + +{{/* + srox.expand $ $spec + + Parses and expands a "specification string" in the following way: + - If $spec is a dictionary, return $spec rendered as a YAML. + - Otherwise, if $spec starts with a backslash character (`\`), return $spec minus the leading + backslash character. + - Otherwise, if $spec starts with an `@` character, strip off the first character and + treat the remainder of the string as a `|`-separated list of file names. Try to load + each referenced file, in order, via `stackrox.getFile`. The result is the first file + that could be successfully loaded. If no file could be loaded, expansion fails. + - Otherwise, return $spec as-is. + */}} +{{- define "srox._expandSingle" -}} + {{- $ := index . 0 -}} + {{- $spec := index . 1 -}} + {{- $context := index . 2 -}} + {{- $result := "" -}} + {{- if kindIs "string" $spec -}} + {{- if hasPrefix "\\" $spec -}} + {{- /* use \ as string-wide escape character */ -}} + {{- $result = trimPrefix "\\" $spec -}} + {{- else if hasPrefix "@" $spec -}} + {{- /* treat as file list (first found matches) */ -}} + {{- /* If the prefix is "@?" expansion will not fail if no files could be found, instead an empty string is returned. */ -}} + {{- $fileSpec := trimPrefix "@" $spec -}} + {{- $allowNotFound := false -}} + {{- if hasPrefix "?" $fileSpec -}} + {{- $allowNotFound = true -}} + {{- $fileSpec = trimPrefix "?" $fileSpec -}} + {{- end -}} + {{- $fileList := regexSplit "\\s*\\|\\s*" ($fileSpec | trim) -1 -}} + {{- $fileRes := dict -}} + {{- $_ := include "srox.loadFile" (list $ $fileRes $fileList) -}} + {{- if and (not $allowNotFound) (not $fileRes.found) -}} + {{- include "srox.fail" (printf "Expanding %s: file reference %q: none of the referenced files were found" $context $spec) -}} + {{- end -}} + {{- $result = default "" $fileRes.contents -}} + {{- else -}} + {{/* treat as raw string */}} + {{- $result = $spec -}} + {{- end -}} + {{- else if not (kindIs "invalid" $spec) -}} + {{- /* render non-string, non-nil values as YAML */ -}} + {{- $result = toYaml $spec -}} + {{- end -}} + {{- $result -}} +{{- end -}} diff --git a/4.3.8/central-services/templates/_format.tpl b/4.3.8/central-services/templates/_format.tpl new file mode 100644 index 0000000..745fe47 --- /dev/null +++ b/4.3.8/central-services/templates/_format.tpl @@ -0,0 +1,14 @@ +{{/* + srox.formatStorageSize $value + + Formats $value as a storage size. $value can be an integer or a string. + If no unit is specified (e.g., if $value is a string), a default unit of + Gigabytes ("Gi" suffix) is assumed. + */}} +{{- define "srox.formatStorageSize" -}} +{{- $val := toString . -}} +{{- if regexMatch "^[0-9]+$" $val -}} + {{- $val = printf "%sGi" $val -}} +{{- end -}} +{{- default "0" $val -}} +{{- end -}} diff --git a/4.3.8/central-services/templates/_helpers.tpl b/4.3.8/central-services/templates/_helpers.tpl new file mode 100644 index 0000000..e87f10f --- /dev/null +++ b/4.3.8/central-services/templates/_helpers.tpl @@ -0,0 +1,68 @@ +{{/* + Misceallaneous helper templates. + */}} + + + + +{{/* + srox.loadFile $ $out $fileName-or-list + + This helper function reads a file. It differs from $.Files.Get in that it also takes + $._rox.meta.fileOverrides into account. Furthermore, it can receive a list of file names, + and will try these files in order. Finally, it indicates whether a file was found via the + $out.found property (as opposed to $.Files.Get, which cannot distinguish between a successful + read of an empty file, and this file not being found). + The file contents will be returned via $out.contents + */}} +{{ define "srox.loadFile" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ $fileNames := index . 2 }} +{{ if not (kindIs "slice" $fileNames) }} + {{ $fileNames = list $fileNames }} +{{ end }} +{{ $contents := index dict "" }} +{{ range $fileName := $fileNames }} + {{ if kindIs "invalid" $contents }} + {{ $contents = index $._rox.meta.fileOverrides $fileName }} + {{ end }} + {{ if kindIs "invalid" $contents }} + {{ range $path, $_ := $.Files.Glob $fileName }} + {{ if kindIs "invalid" $contents }} + {{ $contents = $.Files.Get $path }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ if not (kindIs "invalid" $contents) }} + {{ $_ := set $out "contents" $contents }} +{{ end }} +{{ $_ := set $out "found" (not (kindIs "invalid" $contents)) }} +{{ end }} + + +{{/* + srox.checkGenerated $ $cfgPath + + Checks if the value at configuration path $cfgPath (e.g., "central.adminPassword.value") was + generated. Evaluates to the string "true" if this is the case, and an empty string otherwise. + */}} +{{- define "srox.checkGenerated" -}} +{{- $ := index . 0 -}} +{{- $cfgPath := index . 1 -}} +{{- $genCfg := $._rox._state.generated -}} +{{- $exists := true -}} +{{- range $pathElem := splitList "." $cfgPath -}} + {{- if $exists -}} + {{- if hasKey $genCfg $pathElem -}} + {{- $genCfg = index $genCfg $pathElem -}} + {{- else -}} + {{- $exists = false -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $exists -}} +true +{{- end -}} +{{- end -}} diff --git a/4.3.8/central-services/templates/_image-pull-secrets.tpl b/4.3.8/central-services/templates/_image-pull-secrets.tpl new file mode 100644 index 0000000..9747e26 --- /dev/null +++ b/4.3.8/central-services/templates/_image-pull-secrets.tpl @@ -0,0 +1,85 @@ +{{/* + srox.configureImagePullSecrets $ $cfgName $imagePullSecrets $secretResourceName $defaultSecretNames $namespace + + Configures image pull secrets. + + This function enriches $imagePullSecrets based on the exposed configuration parameters to contain + a list of Kubernetes secret names as `_names` to be used as image pull secrets within the chart + templates. This list contains the following secrets: + + - Secrets referenced via $imagePullSecrets.useExisting. + - Image pull secrets associated with the default service account (if + $imagePullSecrets.useFromDefaultServiceAccount is true). + - $secretResourceName, if $imagePullSecrets.username is set. + - $defaultSecretNames. */}} + +{{ define "srox.configureImagePullSecrets" }} +{{ $ := index . 0 }} +{{ $cfgName := index . 1 }} +{{ $imagePullSecrets := index . 2 }} +{{ $secretResourceName := index . 3 }} +{{ $defaultSecretNames := index . 4 }} +{{ $namespace := index . 5 }} + +{{ $imagePullSecretNames := default list $imagePullSecrets.useExisting }} +{{ if not (kindIs "slice" $imagePullSecretNames) }} + {{ $imagePullSecretNames = regexSplit "\\s*[,;]\\s*" (trim $imagePullSecretNames) -1 }} +{{ end }} +{{ if $imagePullSecrets.useFromDefaultServiceAccount }} + {{ $defaultSA := dict }} + {{ include "srox.safeLookup" (list $ $defaultSA "v1" "ServiceAccount" $namespace "default") }} + {{ if $defaultSA.result }} + {{ range $ips := default list $defaultSA.result.imagePullSecrets }} + {{ if $ips.name }} + {{ $imagePullSecretNames = append $imagePullSecretNames $ips.name }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ $imagePullCreds := dict }} +{{ if $imagePullSecrets._username }} + {{ $imagePullCreds = dict "username" $imagePullSecrets._username "password" $imagePullSecrets._password }} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretResourceName }} +{{ else if $imagePullSecrets._password }} + {{ $msg := printf "Username missing in %q. Whenever an image pull password is specified, a username must be specified as well" $cfgName }} + {{ include "srox.fail" $msg }} +{{ end }} +{{ if and $.Release.IsInstall (not $imagePullSecretNames) (not $imagePullSecrets.allowNone) }} + {{ $msg := printf "You have not specified any image pull secrets, and no existing image pull secrets were automatically inferred. If your registry does not need image pull credentials, explicitly set the '%s.allowNone' option to 'true'" $cfgName }} + {{ include "srox.fail" $msg }} +{{ end }} + +{{ $imagePullSecretNames = concat (append $imagePullSecretNames $secretResourceName) $defaultSecretNames | uniq | sortAlpha }} +{{ $_ := set $imagePullSecrets "_names" $imagePullSecretNames }} +{{ $_ := set $imagePullSecrets "_creds" $imagePullCreds }} + +{{ end }} + +{{ define "srox.configureImagePullSecretsForDockerRegistry" }} +{{ $ := index . 0 }} +{{ $imagePullSecrets := index . 1 }} + +{{/* Setup Image Pull Secrets for Docker Registry. + Note: This must happen afterwards, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} +{{ if $imagePullSecrets._username }} + {{ $dockerAuths := dict }} + {{ range $image := keys $._rox._state.referencedImages }} + {{ $registry := splitList "/" $image | first }} + {{ if eq $registry "docker.io" }} + {{/* Special case docker.io */}} + {{ $registry = "https://index.docker.io/v1/" }} + {{ else }} + {{ $registry = printf "https://%s" $registry }} + {{ end }} + {{ $_ := set $dockerAuths $registry dict }} + {{ end }} + {{ $authToken := printf "%s:%s" $imagePullSecrets._username $imagePullSecrets._password | b64enc }} + {{ range $regSettings := values $dockerAuths }} + {{ $_ := set $regSettings "auth" $authToken }} + {{ end }} + + {{ $_ := set $imagePullSecrets "_dockerAuths" $dockerAuths }} +{{ end }} + +{{ end }} diff --git a/4.3.8/central-services/templates/_images.tpl b/4.3.8/central-services/templates/_images.tpl new file mode 100644 index 0000000..dced29d --- /dev/null +++ b/4.3.8/central-services/templates/_images.tpl @@ -0,0 +1,34 @@ +{{/* + srox.configureImage $ $imageCfg + + Configures settings for a single image by augmenting/completing an existing image configuration + stanza. + + If $imageCfg.fullRef is empty: + First, the image registry is determined by inspecting $imageCfg.registry and, if this is empty, + $._rox.image.registry, ultimately defaulting to `docker.io`. The full image ref is then + constructed from the registry, $imageCfg.name (must be non-empty), and $imageCfg.tag (may be + empty, in which case "latest" is assumed). The result is stored in $imageCfg.fullRef. + + Afterwards (irrespective of the previous check), $imageCfg.fullRef is modified by prepending + "docker.io/" if and only if it did not contain a remote yet (i.e., the part before the first "/" + did not contain a dot (DNS name) or colon (port)). + + Finally, the resulting $imageCfg.fullRef is stored as a dict entry with value `true` in the + $._rox._state.referencedImages dict. + */}} +{{ define "srox.configureImage" }} +{{ $ := index . 0 }} +{{ $imageCfg := index . 1 }} +{{ $imageRef := $imageCfg.fullRef }} +{{ if not $imageRef }} + {{ $imageRef = printf "%s/%s:%s" (coalesce $imageCfg.registry $._rox.image.registry "docker.io") $imageCfg.name (default "latest" $imageCfg.tag) }} +{{ end }} +{{ $imageComponents := splitList "/" $imageRef }} +{{ $firstComponent := index $imageComponents 0 }} +{{ if or (lt (len $imageComponents) 2) (and (not (contains ":" $firstComponent)) (not (contains "." $firstComponent))) }} + {{ $imageRef = printf "docker.io/%s" $imageRef }} +{{ end }} +{{ $_ := set $imageCfg "fullRef" $imageRef }} +{{ $_ = set $._rox._state.referencedImages $imageRef true }} +{{ end }} diff --git a/4.3.8/central-services/templates/_init.tpl b/4.3.8/central-services/templates/_init.tpl new file mode 100644 index 0000000..6708058 --- /dev/null +++ b/4.3.8/central-services/templates/_init.tpl @@ -0,0 +1,285 @@ +{{/* + srox.init $ + + Initialization template for the internal data structures. + This template is designed to be included in every template file, but will only be executed + once by leveraging state sharing between templates. + */}} +{{ define "srox.init" }} + +{{ $ := . }} + +{{/* + On first(!) instantiation, set up the $._rox structure, containing everything required by + the resource template files. + */}} +{{ if not $._rox }} + +{{/* + Initial Setup + */}} + +{{/* + $rox / ._rox is the dictionary in which _all_ data that is modified by the init logic + is stored. + We ensure that it has the required shape, and then right after merging the user-specified + $.Values, we apply some bootstrap defaults. + */}} +{{ $rox := deepCopy $.Values }} +{{ $_ := set $ "_rox" $rox }} + +{{/* Global state (accessed from sub-templates) */}} +{{ $generatedName := printf "stackrox-generated-%s" (randAlphaNum 6 | lower) }} +{{ $state := dict "customCertGen" false "generated" dict "generatedName" $generatedName "notes" list "warnings" list "referencedImages" dict }} +{{ $_ = set $._rox "_state" $state }} + +{{ $configShape := $.Files.Get "internal/config-shape.yaml" | fromYaml }} +{{ $configShapeScanner := $.Files.Get "internal/scanner-config-shape.yaml" | fromYaml}} + +{{ $_ = include "srox.mergeInto" (list $rox $configShape $configShapeScanner (tpl ($.Files.Get "internal/bootstrap-defaults.yaml.tpl") . | fromYaml)) }} +{{ $_ = set $._rox "_configShape" $configShape }} + +{{/* + General validation. + */}} +{{ if ne $.Release.Namespace "stackrox" }} + {{ if $._rox.allowNonstandardNamespace }} + {{ include "srox.note" (list $ (printf "You have chosen to deploy to namespace '%s'." $.Release.Namespace)) }} + {{ else }} + {{ include "srox.fail" (printf "You have chosen to deploy to namespace '%s', not 'stackrox'. If this was accidental, please re-run helm with the '-n stackrox' option. Otherwise, if you need to deploy into this namespace, set the 'allowNonstandardNamespace' configuration value to true." $.Release.Namespace) }} + {{ end }} +{{ end }} + +{{ if ne $.Release.Name $.Chart.Name }} + {{ if $._rox.allowNonstandardReleaseName }} + {{ include "srox.warn" (list $ (printf "You have chosen a release name of '%s', not '%s'. Accompanying scripts and commands in documentation might require adjustments." $.Release.Name $.Chart.Name)) }} + {{ else }} + {{ include "srox.fail" (printf "You have chosen a release name of '%s', not '%s'. We strongly recommend using the standard release name. If you must use a different name, set the 'allowNonstandardReleaseName' configuration option to true." $.Release.Name $.Chart.Name) }} + {{ end }} +{{ end }} + + +{{ if and $.Release.IsInstall (not ._rox.central.persistence.none)}} + {{ include "srox.fail" (printf "Starting from 4.1, we stop creating central PVC during installation. Databases and persistent data are stored in Central DB or external databases. You may use `--set central.persistence.none=true` during Helm install to override default persistence config. Got %v" $._rox.central.persistence) }} +{{ end }} + + +{{ if $._rox.central.db.external }} + {{ if not $._rox.central.db.source.connectionString }} + {{ include "srox.warn" (list $ "You have chosen to bring your own Central DB without providing its connection string. We are using the default source string. To ensure the connection to your Central DB, you may override it with `--set central.db.source.connectionString=`.") }} + {{ end }} + {{ if not $._rox.central.db.password.value }} + {{ include "srox.warn" (list $ "You have chosen to bring your own Central DB without providing its password. We are using a generated password for now. To ensure the connection to your Central DB, you may provide your DB password by `--set central.db.password.value=`.") }} + {{ end }} +{{ end }} + +{{/* Initialize global prefix */}} +{{- include "srox.initGlobalPrefix" (list $) -}} + +{{/* + API Server setup. The problem with `.Capabilities.APIVersions` is that Helm does not + allow setting overrides for those when using `helm template` or `--dry-run`. Thus, + if we rely on `.Capabilities.APIVersions` directly, we lose flexibility for our chart + in these settings. Therefore, we use custom fields such that a user in principle has + the option to inject via `--set`/`-f` everything we rely upon. + */}} +{{ $apiResources := list }} +{{ if not (kindIs "invalid" $._rox.meta.apiServer.overrideAPIResources) }} + {{ $apiResources = $._rox.meta.apiServer.overrideAPIResources }} +{{ else }} + {{ range $apiResource := $.Capabilities.APIVersions }} + {{ $apiResources = append $apiResources $apiResource }} + {{ end }} +{{ end }} +{{ if $._rox.meta.apiServer.extraAPIResources }} + {{ $apiResources = concat $apiResources $._rox.meta.apiServer.extraAPIResources }} +{{ end }} +{{ $apiServerVersion := coalesce $._rox.meta.apiServer.version $.Capabilities.KubeVersion.Version }} +{{ $apiServer := dict "apiResources" $apiResources "version" $apiServerVersion }} +{{ $_ = set $._rox "_apiServer" $apiServer }} + +{{/* + Environment setup - part 1 + */}} +{{ $env := $._rox.env }} + +{{/* Detect openshift version */}} +{{ include "srox.autoSenseOpenshiftVersion" (list $) }} + +{{/* Openshift monitoring */}} +{{ if $._rox.enableOpenShiftMonitoring }} + {{ include "srox.warn" (list . "enableOpenShiftMonitoring option was replaced with monitoring.openshift.enabled") }} + {{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" true)) }} +{{ end }} +{{/* Default `monitoring.openshift.enabled = true` unless `env.openshift != 4`. */}} +{{ if kindIs "invalid" $._rox.monitoring.openshift.enabled }} +{{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" (eq $._rox.env.openshift 4))) }} +{{ end }} +{{ if and $._rox.monitoring.openshift.enabled (ne $._rox.env.openshift 4) }} + {{ include "srox.warn" (list . "'monitoring.openshift.enabled' is set to true, but the chart is not being deployed in an OpenShift 4 cluster. Proceeding with 'monitoring.openshift.enabled=false'.") }} + {{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" false)) }} +{{ end }} +{{ if $._rox.monitoring.openshift.enabled }} + {{ $_ := set $._rox.central "monitoring" dict }} + {{ include "srox.mergeInto" (list $._rox.central.monitoring $._rox.monitoring) }} +{{ end }} + +{{/* Infer GKE, if needed */}} +{{ if kindIs "invalid" $env.platform }} + {{ $platform := "default" }} + {{ if contains "-gke." $._rox._apiServer.version }} + {{ include "srox.note" (list $ "Based on API server properties, we have inferred that you are deploying into a GKE cluster. Set the `env.platform` property to a concrete value to override the auto-sensed value.") }} + {{ $platform = "gke" }} + {{ end }} + {{ $_ := set $env "platform" $platform }} +{{ end }} +{{/* Detect enablePodSecurityPolicies */}} +{{ include "srox.autoSensePodSecurityPolicies" (list $) }} + + +{{ $_ := set $env "installMethod" "helm" }} + + +{{/* Apply defaults */}} +{{ $defaultsCfg := dict }} +{{ $platformCfgFile := dict }} +{{ include "srox.loadFile" (list $ $platformCfgFile (printf "internal/platforms/%s.yaml" $env.platform)) }} +{{ if not $platformCfgFile.found }} + {{ include "srox.fail" (printf "Invalid platform %q. Please select a valid platform, or leave this field unset." $env.platform) }} +{{ end }} +{{ $_ = include "srox.mergeInto" (list $defaultsCfg (fromYaml $platformCfgFile.contents) ($.Files.Get "internal/defaults.yaml" | fromYaml)) }} +{{ $_ = set $rox "_defaults" $defaultsCfg }} +{{ $_ = include "srox.mergeInto" (list $rox $defaultsCfg.defaults) }} + + +{{/* Expand applicable config values */}} +{{ $expandables := $.Files.Get "internal/expandables.yaml" | fromYaml }} +{{ include "srox.expandAll" (list $ $rox $expandables) }} + +{{/* Initial image pull secret setup. + + Always assume that there are `stackrox` and `stackrox-scanner` image pull secrets, + even if they weren't specified. + This is required for updates anyway, so referencing it on first install will minimize a later + diff. */}} +{{ include "srox.configureImagePullSecrets" (list $ "imagePullSecrets" $._rox.imagePullSecrets "stackrox" (list "stackrox" "stackrox-scanner") $.Release.Namespace) }} + +{{/* Global CA setup */}} +{{ $caCertSpec := dict "CN" "StackRox Certificate Authority" "ca" true }} +{{ include "srox.configureCrypto" (list $ "ca" $caCertSpec) }} + +{{/* Additional CAs. */}} +{{ $additionalCAList := list }} +{{ if kindIs "string" $._rox.additionalCAs }} + {{ if trim $._rox.additionalCAs }} + {{ $additionalCAList = append $additionalCAList (dict "name" "ca.crt" "contents" $._rox.additionalCAs) }} + {{ end }} +{{ else if kindIs "slice" $._rox.additionalCAs }} + {{ range $contents := $._rox.additionalCAs }} + {{ $additionalCAList = append $additionalCAList (dict "name" "ca.crt" "contents" $contents) }} + {{ end }} +{{ else if kindIs "map" $._rox.additionalCAs }} + {{ range $name := keys $._rox.additionalCAs | sortAlpha }} + {{ $additionalCAList = append $additionalCAList (dict "name" $name "contents" (get $._rox.additionalCAs $name)) }} + {{ end }} +{{ else if not (kindIs "invalid" $._rox.additionalCAs) }} + {{ include "srox.fail" (printf "Invalid kind %s for additionalCAs" (kindOf $._rox.additionalCAs)) }} +{{ end }} +{{ range $path, $contents := .Files.Glob "secrets/additional-cas/**" }} + {{ $name := trimPrefix "secrets/additional-cas/" $path }} + {{ $additionalCAList = append $additionalCAList (dict "name" $name "contents" (toString $contents)) }} +{{ end }} +{{ $additionalCAs := dict }} +{{ range $idx, $elem := $additionalCAList }} + {{ if not (kindIs "string" $elem.contents) }} + {{ include "srox.fail" (printf "Invalid non-string contents kind %s at index %d (%q) of additionalCAs" (kindOf $elem.contents) $idx $elem.name) }} + {{ end }} + {{/* In a k8s secret, no characters other than alphanumeric, '.', '_' and '-' are allowed. Also, for the + update-ca-certificates script to work, the file names must end in '.crt'. */}} + + {{ $normalizedName := printf "%02d-%s.crt" $idx (regexReplaceAll "[^[:alnum:]._-]" $elem.name "-" | trimSuffix ".crt") }} + {{ $_ := set $additionalCAs $normalizedName $elem.contents }} +{{ end }} +{{ $_ = set $._rox "_additionalCAs" $additionalCAs }} + +{{/* Proxy configuration. + Note: The reason this is different is that unlike the endpoints config, the proxy configuration + might contain sensitive data and thus might _not_ be stored in the always available canonical + values file. However, this is probably rare. Therefore, for this particular instance we do decide + to rely on lookup magic for initially populating the secret with a default proxy config. + However, we won't take any chances, and therefore only create that secret if we can be reasonably + confident that lookup actually works, by trying to lookup the default service account. + */}} +{{ $proxyCfg := $env._proxyConfig }} +{{ $fileOut := dict }} +{{ include "srox.loadFile" (list $ $fileOut "config/proxy-config.yaml") }} +{{ if $fileOut.found }} + {{ if not (kindIs "invalid" $proxyCfg) }} + {{ include "srox.fail" "Both env.proxyConfig was specified, and a config/proxy-config.yaml was found. Please remove/rename the config file, or comment out the env.proxyConfig stanza." }} + {{ end }} + {{ $proxyCfg = $fileOut.contents }} +{{ end }} + +{{/* On first install, create a default proxy config, but only if we can be sure none exists. */}} +{{ if kindIs "invalid" $proxyCfg }} + {{ if $.Release.IsInstall }} + {{ $lookupOut := dict }} + {{ include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "proxy-config") }} + {{ if and $lookupOut.reliable (not $lookupOut.result) }} + {{ $fileOut := dict }} + {{ include "srox.loadFile" (list $ $fileOut "config/proxy-config.yaml.default") }} + {{ $proxyCfg = $fileOut.contents }} + {{ end }} + {{ end }} +{{ end }} +{{ $_ = set $env "_proxyConfig" $proxyCfg }} +{{ $_ = set $._rox "_renderMode" "renderAll" }} + +{{/* + Central setup. + */}} + + +{{ include "srox.centralSetup" $ }} + + +{{/* + Scanner setup. + */}} + +{{ $scannerCfg := $._rox.scanner }} + +{{ if and $scannerCfg.disable (or $.Release.IsInstall $.Release.IsUpgrade) }} + {{/* We generally don't recommend customers run without scanner, so show a warning to the user */}} + {{ $action := ternary "deploy StackRox Central Services without Scanner" "upgrade StackRox Central Services without Scanner (possibly removing an existing Scanner deployment)" $.Release.IsInstall }} + {{ include "srox.warn" (list $ (printf "You have chosen to %s. Certain features dependent on image scanning might not work." $action)) }} +{{ else if not $scannerCfg.disable }} + {{ if and (ne $scannerCfg.mode "full") (ne $scannerCfg.mode "") }} + {{ include "srox.fail" (print "Only scanner full mode is allowed in Central. To solve this, set to full mode: scanner.mode=full.") }} + {{ end }} + {{ include "srox.scannerInit" (list $ $scannerCfg) }} +{{ end }} + + +{{/* + Post-processing steps. + */}} + + +{{/* Compact the post-processing config to prevent it from appearing non-empty if it doesn't + contain any concrete (leaf) values. */}} +{{ include "srox.compactDict" (list $._rox._state.generated -1) }} + +{{/* Setup Image Pull Secrets for Docker Registry. + Note: This must happen afterwards, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} +{{ include "srox.configureImagePullSecretsForDockerRegistry" (list $ ._rox.imagePullSecrets) }} + +{{/* Final warnings based on state. */}} +{{ if $._rox._state.customCertGen }} + {{ include "srox.warn" (list $ "At least one certificate was generated by Helm. Helm limits the generation of custom certificates to RSA private keys, which have poorer computational performance. Consider using roxctl for certificate generation of certificates with ECDSA private keys for improved performance. (THIS IS NOT A SECURITY ISSUE)") }} +{{ end }} + +{{ end }} + +{{ end }} diff --git a/4.3.8/central-services/templates/_injected-ca-bundle.tpl b/4.3.8/central-services/templates/_injected-ca-bundle.tpl new file mode 100644 index 0000000..f831139 --- /dev/null +++ b/4.3.8/central-services/templates/_injected-ca-bundle.tpl @@ -0,0 +1,29 @@ +{{/* + srox.injectedCABundleVolume + + Configures ConfigMap volume to use in a deployment. + */}} +{{- define "srox.injectedCABundleVolume" -}} +{{- if eq ._rox.env.openshift 4 }} +- name: trusted-ca-volume + configMap: + name: injected-cabundle-{{ .Release.Name }} + items: + - key: ca-bundle.crt + path: tls-ca-bundle.pem + optional: true +{{ end }} +{{ end }} + +{{/* + srox.injectedCABundleVolumeMount + + Mounts the srox.injectedCABundle volume to a container. + */}} +{{- define "srox.injectedCABundleVolumeMount" -}} +{{- if eq ._rox.env.openshift 4 }} +- name: trusted-ca-volume + mountPath: /etc/pki/injected-ca-trust/ + readOnly: true +{{ end }} +{{ end }} diff --git a/4.3.8/central-services/templates/_labels.tpl b/4.3.8/central-services/templates/_labels.tpl new file mode 100644 index 0000000..b98b06c --- /dev/null +++ b/4.3.8/central-services/templates/_labels.tpl @@ -0,0 +1,31 @@ +{{/* + srox._labels $labels $ $objType $objName $forPod + + Writes all applicable [pod] labels (including default labels) for $objType/$objName + into $labels. Pod labels are written iff $forPod is true. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.labels". + */}} +{{ define "srox._labels" }} +{{ $labels := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $forPod := index . 4 }} +{{ $_ := set $labels "app.kubernetes.io/name" "stackrox" }} +{{ $_ = set $labels "app.kubernetes.io/managed-by" $.Release.Service }} +{{ $_ = set $labels "helm.sh/chart" (printf "%s-%s" $.Chart.Name ($.Chart.Version | replace "+" "_")) }} +{{ $_ = set $labels "app.kubernetes.io/instance" $.Release.Name }} +{{ $_ = set $labels "app.kubernetes.io/version" $.Chart.AppVersion }} +{{ $_ = set $labels "app.kubernetes.io/part-of" "stackrox-central-services" }} +{{ $component := regexReplaceAll "^.*/\\d{2}-([a-z]+)-\\d{2}-[^/]+\\.yaml" $.Template.Name "${1}" }} +{{ if not (contains "/" $component) }} + {{ $_ = set $labels "app.kubernetes.io/component" $component }} +{{ end }} +{{ $metadataNames := list "labels" }} +{{ if $forPod }} + {{ $metadataNames = append $metadataNames "podLabels" }} +{{ end }} +{{ include "srox._customizeMetadata" (list $ $labels $objType $objName $metadataNames) }} +{{ end }} diff --git a/4.3.8/central-services/templates/_lookup.tpl b/4.3.8/central-services/templates/_lookup.tpl new file mode 100644 index 0000000..2dc0aa9 --- /dev/null +++ b/4.3.8/central-services/templates/_lookup.tpl @@ -0,0 +1,40 @@ +{{/* + srox.safeLookup $ $out $apiVersion $kind $ns $name + + This function does nothing if $.meta.useLookup is false; otherwise, it will + perform a `lookup $apiVersion $kind $ns $name` operation and store the result in + $out.result. + + Additionally, if a lookup was attempted, $out.reliable will contain a bool indicating + whether the result of lookup can be relied upon. This is determined to be the case if + the default service account in the release namespace can be found. + */}} +{{ define "srox.safeLookup" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ if $._rox.meta.useLookup }} + {{ if kindIs "invalid" $._rox._state.lookupWorks }} + {{ $testOut := dict }} + {{ include "srox._doLookup" (list $ $testOut "v1" "ServiceAccount" $.Release.Namespace "default") }} + {{ $_ := set $._rox._state "lookupWorks" ($testOut.result | not | not) }} + {{ end }} + {{ include "srox._doLookup" . }} + {{ $_ := set $out "reliable" $._rox._state.lookupWorks }} +{{ end }} +{{ end }} + + +{{/* + srox._doLookup $ $out $apiVersion $kind $ns $name + + Calls "lookup" with arguments $apiVersion $kind $ns $name, and stores the result + in $out.result. + + This function exists to prevent a parse error if the lookup function isn't defined. It does + so by deferring the execution of lookup to a template string instantiated via `tpl`. + */}} +{{ define "srox._doLookup" }} +{{ $ := index . 0 }} +{{ $tplArgs := dict "Template" $.Template "out" (index . 1) "apiVersion" (index . 2) "kind" (index . 3) "ns" (index . 4) "name" (index . 5) }} +{{ $_ := tpl "{{ $_ := set .out \"result\" (lookup .apiVersion .kind .ns .name) }}" $tplArgs }} +{{ end }} diff --git a/4.3.8/central-services/templates/_metadata.tpl b/4.3.8/central-services/templates/_metadata.tpl new file mode 100644 index 0000000..3ed131f --- /dev/null +++ b/4.3.8/central-services/templates/_metadata.tpl @@ -0,0 +1,194 @@ +{{/* + srox.labels $ $objType $objName + + Format labels for $objType/$objName as YAML. + */}} +{{- define "srox.labels" -}} +{{- $labels := dict -}} +{{- $_ := include "srox._labels" (append (prepend . $labels) false) -}} +{{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.podLabels $ $objType $objName + + Format pod labels for $objType/$objName as YAML. + */}} +{{- define "srox.podLabels" -}} +{{- $labels := dict -}} +{{- $_ := include "srox._labels" (append (prepend . $labels) true) -}} +{{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.annotations $ $objType $objName + + Format annotations for $objType/$objName as YAML. + */}} +{{- define "srox.annotations" -}} +{{- $annotations := dict -}} +{{- $_ := include "srox._annotations" (append (prepend . $annotations) false) -}} +{{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.podAnnotations $ $objType $objName + + Format pod annotations for $objType/$objName as YAML. + */}} +{{- define "srox.podAnnotations" -}} +{{- $annotations := dict -}} +{{- $_ := include "srox._annotations" (append (prepend . $annotations) true) -}} +{{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.envVars $ $objType $objName $containerName + + Format environment variables for container $containerName in + $objType/$objName as YAML. + */}} +{{- define "srox.envVars" -}} +{{- $envVars := dict -}} +{{- $_ := include "srox._envVars" (prepend . $envVars) -}} +{{- range $k := keys $envVars | sortAlpha -}} +{{- $v := index $envVars $k }} +- name: {{ quote $k }} +{{- if kindIs "map" $v }} + {{- toYaml $v | nindent 2 }} +{{- else }} + value: {{ quote $v }} +{{- end }} +{{ end -}} +{{- end -}} + +{{/* + srox._annotations $annotations $ $objType $objName $forPod + + Writes all applicable [pod] annotations (including default annotations) for + $objType/$objName into $annotations. Pod labels are written iff $forPod is true. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.annotations". + */}} +{{ define "srox._annotations" }} +{{ $annotations := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $forPod := index . 4 }} +{{ $_ := set $annotations "meta.helm.sh/release-namespace" $.Release.Namespace }} +{{ $_ = set $annotations "meta.helm.sh/release-name" $.Release.Name }} +{{ $_ = set $annotations "owner" "stackrox" }} +{{ $_ = set $annotations "email" "support@stackrox.com" }} +{{ $metadataNames := list "annotations" }} +{{ if $forPod }} + {{ $metadataNames = append $metadataNames "podAnnotations" }} +{{ end }} +{{ include "srox._customizeMetadata" (list $ $annotations $objType $objName $metadataNames) }} +{{ end }} + +{{/* + srox._envVars $envVars $ $objType $objName $containerName + + Writes all applicable environment variables for $objType/$objName + into $envVars. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.envVars". + */}} +{{ define "srox._envVars" }} +{{ $envVars := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $containerName := index . 4 }} +{{ $metadataNames := list "envVars" }} +{{ include "srox._customizeMetadata" (list $ $envVars $objType $objName $metadataNames) }} +{{ if $containerName }} + {{ $containerKey := printf "/%s" $containerName }} + {{ $envVarsForContainer := index $envVars $containerKey }} + {{ if $envVarsForContainer }} + {{ include "srox.destructiveMergeOverwrite" (list $envVars $envVarsForContainer) }} + {{ end }} +{{ end }} + +{{/* Remove all entries starting with / */}} +{{ range $key, $_ := $envVars }} + {{ if hasPrefix "/" $key }} + {{ $_ := unset $envVars $key }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox._customizeMetadata $ $metadata $objType $objName $metadataNames + + Writes custom key/value metadata to $metadata by consulting all sub-dicts with names in + $metadataNames under the applicable custom metadata locations (._rox.customize, + ._rox.customize.other.$objType/*, ._rox.customize.other.$objType/$objName, and + ._rox.customizer.$objName [workloads only]). Dictionaries are consulted in this order, with + values from dictionaries consulted later overwriting values from dictionaries consulted + earlier. + */}} +{{ define "srox._customizeMetadata" }} +{{ $ := index . 0 }} +{{ $metadata := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $metadataNames := index . 4 }} + +{{ $overrideDictPaths := list "" (printf "other.%s/*" $objType) (printf "other.%s/%s" $objType $objName) }} +{{ if has $objType (list "deployment" "daemonset") }} + {{ $overrideDictPaths = append $overrideDictPaths $objName }} +{{ end }} + +{{ range $dictPath := $overrideDictPaths }} + {{ $customizeDict := $._rox.customize }} + {{ if $dictPath }} + {{ $resolvedOut := dict }} + {{ include "srox.safeDictLookup" (list $._rox.customize $resolvedOut $dictPath) }} + {{ $customizeDict = $resolvedOut.result }} + {{ end }} + {{ if $customizeDict }} + {{ range $metadataName := $metadataNames }} + {{ $customMetadata := index $customizeDict $metadataName }} + {{ include "srox.destructiveMergeOverwrite" (list $metadata $customMetadata) }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{/* Add namespace specific prefixes for global resources to avoid resource name clashes for multi-namespace deployments. */}} +{{- define "srox.globalResourceName" -}} +{{- $ := index . 0 -}} +{{- $name := index . 1 -}} + +{{- if eq $.Release.Namespace "stackrox" -}} + {{- /* Standard namespace, use resource name as is. */ -}} + {{- $name -}} +{{- else -}} + {{- /* Add global prefix to resource name. */ -}} + {{- printf "%s-%s" $._rox.globalPrefix (trimPrefix "stackrox-" $name) -}} +{{- end -}} +{{- end -}} + +{{/* + srox.initGlobalPrefix $ + + Initializes prefix for global resources. + */}} +{{- define "srox.initGlobalPrefix" -}} +{{- $ := index . 0 -}} +{{ if kindIs "invalid" $._rox.globalPrefix }} + {{ if eq $.Release.Namespace "stackrox" }} + {{ $_ := set $._rox "globalPrefix" "stackrox" }} + {{ else }} + {{ $_ := set $._rox "globalPrefix" (printf "stackrox-%s" (trimPrefix "stackrox-" $.Release.Namespace)) }} + {{ end }} +{{ end }} + +{{ if ne $._rox.globalPrefix "stackrox" }} + {{ include "srox.note" (list $ (printf "Global Kubernetes resources are prefixed with '%s'." $._rox.globalPrefix)) }} +{{- end -}} +{{- end -}} diff --git a/4.3.8/central-services/templates/_openshift.tpl b/4.3.8/central-services/templates/_openshift.tpl new file mode 100644 index 0000000..85201cb --- /dev/null +++ b/4.3.8/central-services/templates/_openshift.tpl @@ -0,0 +1,47 @@ +{{/* + srox.autoSenseOpenshiftVersion $ + + This function detects the OpenShift version automatically based on the cluster the Helm chart is installed onto. + It writes the result to ._rox.env.openshift as an integer. + Possible results are: + - 3 (OpenShift 3) + - 4 (OpenShift 4) + - 0 (Non-Openshift cluster) + + If "true" is passed for $._rox.env.openshift the OpenShift version is detected based on the Kubernetes cluster version. + If the Kubernetes version is not available (i.e. when using Helm template) auto-sensing falls back on OpenShift 3 to be + backward compatible. + */}} + +{{ define "srox.autoSenseOpenshiftVersion" }} + +{{ $ := index . 0 }} +{{ $env := $._rox.env }} + +{{/* Infer OpenShift, if needed */}} +{{ if kindIs "invalid" $env.openshift }} + {{ $_ := set $env "openshift" (has "apps.openshift.io/v1" $._rox._apiServer.apiResources) }} +{{ end }} + +{{/* Infer openshift version */}} +{{ if and $env.openshift (kindIs "bool" $env.openshift) }} + {{/* Parse and add KubeVersion as semver from built-in resources. This is necessary to compare valid integer numbers. */}} + {{ $kubeVersion := semver $.Capabilities.KubeVersion.Version }} + + {{/* Default to OpenShift 3 if no openshift resources are available, i.e. in helm template commands */}} + {{ if not (has "apps.openshift.io/v1" $._rox._apiServer.apiResources) }} + {{ $_ := set $._rox.env "openshift" 3 }} + {{ else if gt $kubeVersion.Minor 11 }} + {{ $_ := set $env "openshift" 4 }} + {{ else }} + {{ $_ := set $env "openshift" 3 }} + {{ end }} + {{ include "srox.note" (list $ (printf "Based on API server properties, we have inferred that you are deploying into an OpenShift %d.x cluster. Set the `env.openshift` property explicitly to 3 or 4 to override the auto-sensed value." $env.openshift)) }} +{{ end }} +{{ if not (kindIs "bool" $env.openshift) }} + {{ $_ := set $env "openshift" (int $env.openshift) }} +{{ else if not $env.openshift }} + {{ $_ := set $env "openshift" 0 }} +{{ end }} + +{{ end }} diff --git a/4.3.8/central-services/templates/_psp.tpl b/4.3.8/central-services/templates/_psp.tpl new file mode 100644 index 0000000..bffb2a0 --- /dev/null +++ b/4.3.8/central-services/templates/_psp.tpl @@ -0,0 +1,19 @@ +{{/* + srox.autoSensePodSecurityPolicies $ + */}} + +{{ define "srox.autoSensePodSecurityPolicies" }} + +{{ $ := index . 0 }} +{{ $system := $._rox.system }} + +{{ if kindIs "invalid" $system.enablePodSecurityPolicies }} + {{ $_ := set $system "enablePodSecurityPolicies" (has "policy/v1beta1" $._rox._apiServer.apiResources) }} + {{ if $system.enablePodSecurityPolicies }} + {{ include "srox.note" (list $ (printf "PodSecurityPolicies are enabled, since your environment supports them according to API server properties.")) }} + {{ else }} + {{ include "srox.note" (list $ (printf "PodSecurityPolicies are disabled, since your environment does not support them according to API server properties.")) }} + {{ end }} +{{ end }} + +{{ end }} diff --git a/4.3.8/central-services/templates/_reporting.tpl b/4.3.8/central-services/templates/_reporting.tpl new file mode 100644 index 0000000..621e284 --- /dev/null +++ b/4.3.8/central-services/templates/_reporting.tpl @@ -0,0 +1,34 @@ +{{/* + srox.fail $message + + Print a nicely-formatted fatal error message and exit. + */}} +{{ define "srox.fail" }} +{{ printf "\n\nFATAL ERROR:\n%s" . | wrap 100 | fail }} +{{ end }} + +{{/* + srox.warn $ $message + + Add $message to the list of encountered warnings. + */}} +{{ define "srox.warn" }} +{{ $ := index . 0 }} +{{ $msg := index . 1 }} +{{ $warnings := $._rox._state.warnings }} +{{ $warnings = append $warnings $msg }} +{{ $_ := set $._rox._state "warnings" $warnings }} +{{ end }} + +{{/* + srox.note $ $message + + Add $message to the list notes that will be shown to the user after installation/upgrade. + */}} +{{ define "srox.note" }} +{{ $ := index . 0 }} +{{ $msg := index . 1 }} +{{ $notes := $._rox._state.notes }} +{{ $notes = append $notes $msg }} +{{ $_ := set $._rox._state "notes" $notes }} +{{ end }} diff --git a/4.3.8/central-services/templates/_scanner_init.tpl b/4.3.8/central-services/templates/_scanner_init.tpl new file mode 100644 index 0000000..75fbe95 --- /dev/null +++ b/4.3.8/central-services/templates/_scanner_init.tpl @@ -0,0 +1,40 @@ +{{/* + srox.scannerInit . $scannerConfig + + Initializes the scanner configuration. The scanner chart has two modes "full" and + "slim". + The "full" mode is used for stand-alone deployments, mostly along with StackRox's Central service. In this + mode, the image contains vulnerability data and the Helm chart can create its own certificates. + + The "slim" mode is used to deploy Scanner with a smaller image and does not generate TLS certificates, + typically deployed within a Secured Cluster to scan images stored in a registry only accessible to the current cluster. + The scanner chart defaults to "full" mode if no mode was provided. + + $scannerConfig contains all values which are configured by the user. The structure can be viewed in the according + config-shape. See internal/scanner-config-shape.yaml. + */}} + +{{ define "srox.scannerInit" }} + +{{ $ := index . 0 }} +{{ $scannerCfg := index . 1 }} + +{{ if or (eq $scannerCfg.mode "") (eq $scannerCfg.mode "full") }} + {{ include "srox.configureImage" (list $ $scannerCfg.image) }} + {{ include "srox.configureImage" (list $ $scannerCfg.dbImage) }} + + {{ $scannerCertSpec := dict "CN" "SCANNER_SERVICE: Scanner" "dnsBase" "scanner" }} + {{ include "srox.configureCrypto" (list $ "scanner.serviceTLS" $scannerCertSpec) }} + + {{ $scannerDBCertSpec := dict "CN" "SCANNER_DB_SERVICE: Scanner DB" "dnsBase" "scanner-db" }} + {{ include "srox.configureCrypto" (list $ "scanner.dbServiceTLS" $scannerDBCertSpec) }} +{{ else if eq $scannerCfg.mode "slim" }} + {{ include "srox.configureImage" (list $ $scannerCfg.slimImage) }} + {{ include "srox.configureImage" (list $ $scannerCfg.slimDBImage) }} +{{ else }} + {{ include "srox.fail" (printf "Unknown scanner mode %s" $scannerCfg.mode) }} +{{ end }} + +{{ include "srox.configurePassword" (list $ "scanner.dbPassword") }} + +{{ end }} diff --git a/4.3.8/central-services/values-private.yaml.example b/4.3.8/central-services/values-private.yaml.example new file mode 100644 index 0000000..41254aa --- /dev/null +++ b/4.3.8/central-services/values-private.yaml.example @@ -0,0 +1,178 @@ +# StackRox Kubernetes Security Platform - Central Services Chart +# PRIVATE configuration file. +# +# This file contains sensitive values relevant for the deployment of the +# StackRox Kubernetes Platform Central Services components. +# +# Apart from image pull secrets (see below), all the values in this file are +# optional or can be automatically generated at deployment time. +# Moreover, this file does not need to be provided (e.g., via `-f`) to a `helm upgrade` +# command, even if custom values are used - the previously set values +# will simply be preserved. +# +# The following values typically require user input, as they cannot be automatically generated +# (though each of them can be omitted): +# - `imagePullSecrets.username` and `imagePullSecrets.password` +# - `env.proxyConfig` +# - `central.defaultTLS` +# +# If you do choose to use this file (either by manually filling in values, or by +# generating it via the `roxctl central generate` command family), you must store +# it in a safe and secure place, such as a secrets management system. +# + +# # BEGIN CONFIGURATION VALUES SECTION + +# # Image pull credentials. If you do not specify these, you need to specify one of +# # the following: +# # - `imagePullSecrets.allowNone=true`: in case your registry allows pulling images without +# # credentials. +# # - `imagePullSecrets.useExisting="secret1;secret2;..."`: in case you have pre-existing image +# # pull secrets with the given name already created in the target namespace. +# # - `imagePullSecrets.useFromDefaultServiceAccount=true`: in case the default service account +# # in the target namespace is configured with sufficiently scoped image pull secrets. +# # If you do not know if any of the above applies to your situation, your best course of +# # action is probably to enter your image pull credentials here. +# imagePullSecrets: +# username: +# password: +# +# # Proxy configuration. This will only be required if you are running in an environment +# # where internet access is not possible by default. +# # Since this configuration may contain a proxy password, it is treated as a sensitive +# # piece of configuration. +# # The following example is a stripped-down one. For a full documentation, see the file +# # `config/proxy-config.yaml.default` that is shipped with this chart. +# env: +# proxyConfig: | +# url: http://proxy.name:port +# username: username +# password: password +# excludes: +# - some.domain +# +# +# # TLS Certificate Configuration. +# # Most of the following values are not typically required to be populated manually. You can +# # either omit them, in which case they will be auto-generated upon initial installation, +# # or they are populated when you invoke `roxctl central generate` to generate deployment +# # files. +# +# # Certificate Authority (CA) certificate for TLS certificates used internally +# # by StackRox services. +# ca: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Secret configuration options for the StackRox Central deployment. +# central: +# # Private key to use for signing JSON web tokens (JWTs), which are used +# # for authentication. Omit to auto-generate (initial deployment) or use existing +# # (upgrade). +# jwtSigner: +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# # Internal "central.stackrox" service TLS certificate for the Central deployment. +# # Omit to auto-generate (initial deployment) or use existing (upgrade). +# serviceTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Default (user-facing) TLS certificate. +# # NOTE: In contrast to almost all other configuration options, this IS expected +# # to be manually populated. While any existing default TLS certificate secret +# # will be re-used on upgrade if this is omitted, nothing will be created on +# # initial deployment if this is not populated. +# defaultTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Administrator password for logging in to the StackRox portal. +# # You can either specify a plaintext password here, or an htpasswd file with a +# # bcrypt-encrypted password. +# # If you omit this setting, a password will be automatically generated upon initial +# # installation, and the existing administrator password secret will be re-used upon +# # upgrades. +# adminPassword: +# # The plaintext value of the administrator password. If you specify a password here, +# # you must omit the `htpasswd` setting. +# value: +# # The htpasswd contents of the administrator login credentials. If you specify a +# # value here, you must omit the `value` setting. +# # The password hash MUST be bcrypt. +# htpasswd: | +# admin: +# +# # Secret configuration options for the StackRox Central DB deployment. +# db: +# # The password to be used for authenticating central database access IF USING POSTGRES. +# # This is not user-relevant and only serves to properly secure the database with a +# # pre-shared secret. If this setting is omitted, a password will be automatically generated +# # upon initial deployment, and the existing password will be used upon upgrades. +# password: +# # The plaintext value of the administrator password. +# value: +# # Internal "central-db.stackrox.svc" service TLS certificate for the Central DB deployment. +# # Omit to auto-generate (initial deployment) or use existing (upgrade). +# serviceTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Secret configuration options for the StackRox Central deployment. +# scanner: +# # The password to be used for authenticating database access. This is not user-relevant +# # and only serves to properly secure the database with a pre-shared secret. If this +# # setting is omitted, a password will be automatically generated upon initial deployment, +# # and the existing password will be used upon upgrades. +# dbPassword: +# value: +# +# # Internal "scanner.stackrox.svc" service TLS certificate for the Scanner deployment. +# # Omit to auto-generate (initial deployment) or use existing (upgrade). +# serviceTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Internal "scanner-db.stackrox" service TLS certificate for the Scanner DB deployment. +# # Omit to auto-generate (initial deployment) or use existing (upgrade). +# dbServiceTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- diff --git a/4.3.8/central-services/values-public.yaml.example b/4.3.8/central-services/values-public.yaml.example new file mode 100644 index 0000000..b4e03e2 --- /dev/null +++ b/4.3.8/central-services/values-public.yaml.example @@ -0,0 +1,538 @@ +# StackRox Kubernetes Security Platform - Central Services Chart +# PUBLIC configuration file. +# +# This file contains general configuration values relevant for the deployment of the +# StackRox Kubernetes Platform Central Services components, which do not contain or reference +# sensitive data. This file can and should be stored in a source code management system +# and should be referenced on each `helm upgrade`. +# +# Most of the values in this file are optional, and you only should need to make modifications +# if the default deployment configuration is not sufficient for you for whatever reason. +# The most notable exception is the `imagePullSecrets` section, which needs to be configured +# according to the registry access in your environment. +# +# Other than that, the following are sections most likely require custom configuration: +# - `image.registry`: if you are pulling images from a registry other than `stackrox.io`. +# - `env.offlineMode`: if you want to run StackRox in offline mode. +# - `central.endpointsConfig`: if you want to expose additional endpoints (such as endpoints +# without TLS) in Central. +# - `central.resources`: if the default resource configuration for Central is not adequate +# for your environment. +# - `db.persistence`: for configuring where Central DB stores its postgres database volume. + +# # BEGIN CONFIGURATION VALUES SECTION + +# imagePullSecrets: +# # allowNone=true indicates that no image pull secrets are required to be configured +# # upon initial deployment. Use this setting if you are using a cluster-private registry +# # that does not require authentication. +# allowNone: false +# +# # useExisting specifies a list of existing Kubernetes image pull secrets in the target +# # namespace that should be used for trying to pull StackRox images. Use this if you have +# # your custom way of injecting image pull secrets. +# useExisting: +# - secret1 +# - secret2 +# +# # useFromDefaultServiceAccount=true will instruct the deployment logic to use any +# # image pull secrets referenced by the default service account in the target namespace. +# # This is a common way to grant namespace-wide access to a Docker image registry. +# # This behavior is the default, set the value to `false` if you do not want this. +# useFromDefaultServiceAccount: true +# +# image: +# # The registry relative to which all image references are resolved, unless +# # a specific registry is provided for particular workloads which takes precedence +# # (see `central.image`, `db.image`, `scanner.image`, and `scanner.dbImage` below). +# # This can be just a registry hostname such as `stackrox.io`, or a registry hostname with +# # a "remote" component such as `us.gcr.io/my-stackrox-mirror`. +# registry: us.gcr.io/my-stackrox-mirror +# +# env: +# # Treat the environment as an OpenShift cluster. Leave this unset to use auto-detection +# # based on available API resources on the server. +# # Set it to true to auto-detect the OpenShift version, otherwise set it explicitly. +# # Possible values: null, false, true, 3, 4 +# openshift: false +# +# # Whether the target cluster is an Istio-enabled cluster. If you deploy via `helm install`, +# # this can typically be determined automatically, so we recommend to not set a value here. +# # Set to true or false explicitly to override the auto-sensing logic only. +# istio: false +# +# # The "platform" of the target cluster into which StackRox is being deployed. This can +# # be the name of an infrastructure provider or product, and will tailor the StackRox +# # deployment to the respective target environment. Currently, the only supported platforms +# # are "default" and "gke". +# # If you deploy via `helm install`, the environment can typically be determined automatically, +# # choose a fixed value here only if you want to override the auto-sensing logic. +# platform: default +# +# # offlineMode=true instructs StackRox to not attempt any outgoing connections to the +# # internet. Use this in air-gapped environments, where it's important that workloads do +# # not even try to make outbound connections. Defaults to `false` when omitted. +# offlineMode: false +# +# # Additional certificate authorities (CAs) to trust, besides system roots. +# # Use this setting if Central or Scanner need to reach out to services that use certificates +# # issued by an authority in your organization, but are NOT globally trusted. In these cases, +# # specify the root CA certificate of your organization. +# additionalCAs: +# acme-labs-ca.crt: | +# -----BEGIN CERTIFICATE----- +# [... base64 (PEM) encoded certificate data ...] +# -----END CERTIFICATE----- +# +# # Public configuration options for the StackRox Central deployment. +# central: +# # General configuration options for the Central deployment. +# # See the `config/central/config.yaml.default` file that is shipped with this chart +# # for a fully documented version. +# config: | +# maintenance: +# safeMode: false +# compaction: +# enabled: true +# bucketFillFraction: .5 +# freeFractionThreshold: 0.75 +# # Configuration option for rolling back to a previous version after an upgrade has been completed. +# # Default to none. +# # By default, the user may initiate a rollback if upgrade fails before Central has started. +# # Users may rollback to their previous version once Central has started, but this may result in data loss, +# # so users must explicitly specify the version they are rolling back to in order to acknowledge the effects. +# forceRollbackVersion: 3.0.58.0 +# +# # Additional endpoints configuration for the Central deployment. +# # See the `config/central/endpoints.yaml.default` file that is shipped with this chart +# # for a fully documented version. +# endpointsConfig: | +# endpoints: +# - listen: ":8080" +# protocols: +# - http +# tls: +# disable: true +# +# # If you want to use a monitoring solution such as Prometheus, set the following value to +# # "true" to make a /metrics endpoint for Central available on port 9090. +# exposeMonitoring: true +# +# # If you want to enforce StackRox Central to only run on certain nodes, you can specify +# # a node selector here to make sure Central can only be scheduled on Nodes with the +# # given label. This is particular relevant for the "hostPath" persistence type. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-central +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # Central is single-homed, so avoid preemptible nodes. +# - weight: 100 +# preference: +# matchExpressions: +# - key: cloud.google.com/gke-preemptible +# operator: NotIn +# values: +# - "true" +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/infra +# operator: Exists +# - weight: 25 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/compute +# operator: Exists +# # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in +# # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/master +# operator: DoesNotExist +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/control-plane +# operator: DoesNotExist +# +# # Configures the Central image to be used. Most users will only need to configure a +# # custom registry (if any) at the global scope, and do not require any settings here. +# image: +# # A custom registry that will override the global `image.registry` setting for the +# # Central image. +# registry: us.gcr.io/stackrox-central-repo +# +# # A custom image name that will override the default `main`. +# name: custom-main +# +# # A custom image tag that will override the default tag based on the current +# # StackRox version. +# # IMPORTANT: If you set a value here, you will lose the ability to simply upgrade +# # by running `helm upgrade` against a more recent chart version. You MUST increment +# # the version referenced in this tag for every upgrade. It is therefore strongly +# # recommended that if you choose to mirror StackRox images in your own registry, +# # you preserve all image tags as-is. +# tag: custom-version +# +# # A full image name override that will be used as-is for the StackRox Central image. +# # This is only required in very rare circumstances, and its use is strongly discouraged. +# # If set, all other image-related values will be ignored for the StackRox Central image. +# # The following example value lists the full image ref that would be constructed from +# # the above components. +# fullRef: "us.gcr.io/stackrox-central-repo/custom-main:custom-version" +# +# # Custom resource overrides for the Central deployment. Use this if your environment is +# # very large or very small, and the default resource configuration does not provide +# # satisfactory performance. +# resources: +# requests: +# memory: "4Gi" +# cpu: "1500m" +# limits: +# memory: "8Gi" +# cpu: "4000m" +# +# # Configuration for exposing the StackRox Central deployment for external access. +# # Generally, only ONE of the nested values should be specified. If none is specified, +# # the Central deployment will not be exposed, and you must either manually expose it, +# # or access it via port-forwarding. +# exposure: +# # Exposure via a Kubernetes LoadBalancer service. +# loadBalancer: +# enabled: true +# # The port on which to expose StackRox Central. Defaults to 443. +# port: 443 +# # The static IP to assign to the load balancer. Defaults to dynamic. +# ip: 10.0.0.0 +# +# # Exposure via a Kubernetes NodePort service. +# nodePort: +# enabled: true +# # The port on the node under which to expose the service. Omit this for +# # letting Kubernetes automatically select a node port (recommended). +# port: 32000 +# +# # Exposure via an OpenShift route. Only available for OpenShift clusters +# route: +# enabled: true +# +# # Additional volume mounts for the Central container. Only few people will require this. +# extraMounts: +# - name: my-configmap # the name of the volume +# # The source of the volume. This will be embedded as-is in the `volume:` section of the +# # pod spec. +# source: +# configMap: +# name: my-configmap +# # The mount point of the volume. This will be embedded as-is in the `volumeMounts:` section +# # of the pod spec. +# mount: +# mountPath: /etc/my-config-data +# +# # Public configuration options for the StackRox Central DB: +# db: +# # If you want to enforce StackRox Central DB to only run on certain nodes, you can specify +# # a node selector here to make sure Central can only be scheduled on Nodes with the +# # given label. This is particular relevant for the "hostPath" persistence type. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-central-db +# +# # If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# # External signifies that a Postgres wire-compatible database has already been deployed and a Central DB pod +# # does not need to be deployed +# external: false +# +# # Customized Central DB source configurations to connect to Postgres database. +# # Default configurations are applied if the configurations are omitted. +# source: +# # ConnectionString should not be specified if the Central DB deployment is being managed by the helm chart +# # The connection string must be in the format described here https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING +# # The only connection string format supported is as specified in "34.1.1.1. Keyword/Value Connection Strings" +# # client_encoding=UTF8 is required in any connection string and the only supported encoding +# # statementTimeoutMs is ignored for external database connections +# # If using a connection that supports "statement_timeout" it is recommended to include "statement_timeout=1200000" +# # Do NOT use a connection string with a password field. Instead specify the value below in the password section in values-private.yaml. +# connectionString: "host=central-db.stackrox port=5432 user=postgres sslmode=verify-full" +# minConns: 10 +# maxConns: 90 +# statementTimeoutMs: 1200000 +# +# # Configures the Central DB image to be used. Most users will only need to configure a +# # custom registry (if any) at the global scope, and do not require any settings here. +# image: +# # A custom registry that will override the global `image.registry` setting for the +# # Central DB image. +# registry: us.gcr.io/central-db +# # A custom image name that will override the default `main`. +# name: custom-central-db +# # A custom image tag that will override the default tag based on the current +# # StackRox version. +# tag: custom-version +# +# # Custom resource overrides for the Central DB deployment. +# resources: +# requests: +# memory: "8Gi" +# cpu: "4" +# limits: +# memory: "16Gi" +# cpu: "8" +# +# # Persistence configuration for the StackRox Central DB. +# # Exactly ONE of the nested values should be specified. If none is specified, +# # the StackRox Central DB will be configured with the default PVC-based persistence. +# persistence: +# # The path on the node where to store the StackRox Central DB volume +# # when using host path persistence. +# hostPath: /var/lib/central-db +# # The persistent volume claim details when storing the StackRox database +# # on a persistent volume managed by a Kubernetes persistent volume claim (PVC). +# persistentVolumeClaim: +# # The name of the claim. This defaults to central-db if not set. +# claimName: central-db +# # Whether to create the claim upon deployment. The default is true; set this to false +# # if you have a pre-existing persistent volume claim that you want to use. +# createClaim: true +# # The storage class of the persistent volume. +# storageClass: stackrox-gke-ssd +# # The size of the persistent volume managed by the claim, in Gigabytes (or with an +# # explicit unit, such as "1Ti"). Defaults to 100Gi. +# size: 100 +# # If you want to bind a preexisting persistent volume, you can specify it here. +# volume: +# volumeSpec: +# # The section includes volume type specific config, the volume type can be: +# # gcePersistentDisk, hostpath, filestore(nfs) etc. +# gcePersistentDisk: +# # Type specific parameters. The specified persistent volume should have +# # been created. +# pdName: gke-pv +# +# # Public configuration options for the StackRox Scanner. +# scanner: +# # disable=true will cause the StackRox Kubernetes Security Platform to be +# # deployed without the StackRox Scanner, meaning that certain functionalities +# # may not be available. If this setting is changed prior to a `helm upgrade` +# # invocation, the existing StackRox scanner deployment will be removed. +# disable: false +# +# # The number of replicas for the Scanner deployment. If autoscaling is enabled (see below), +# # this determines the initial number of replicas. +# replicas: 3 +# +# # The log level for the scanner deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce StackRox Scanner to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-scanner +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# podAntiAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 100 +# podAffinityTerm: +# labelSelector: +# matchLabels: +# app: scanner +# topologyKey: kubernetes.io/hostname +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/infra +# operator: Exists +# - weight: 25 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/compute +# operator: Exists +# # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in +# # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/master +# operator: DoesNotExist +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/control-plane +# operator: DoesNotExist +# +# # If you want to enforce StackRox Scanner DB to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner DB can only be scheduled on Nodes with the +# # given label. +# dbNodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-scanner-db +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# dbTolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# # Configuration for autoscaling the Scanner deployment. +# autoscaling: +# # disable=true causes autoscaling to be disabled. All other settings in this section +# # will have no effect. +# disable: false +# # The minimum number of replicas for autoscaling. The following value is the default. +# minReplicas: 2 +# # The maximum number of replicas for autoscaling. The following value is the default. +# maxReplicas: 5 +# +# # Custom resource overrides for the Scanner deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "4Gi" +# cpu: "2000m" +# +# # Custom resource overrides for the Scanner DB deployment. +# dbResources: +# limits: +# cpu: "2000m" +# memory: "4Gi" +# requests: +# cpu: "200m" +# memory: "200Mi" +# +# # Custom configuration of the image to be used for the Scanner deployment. +# # See `central.image` for a full example. +# image: +# registry: us.gcr.io/stackrox-scanner-repo +# name: scanner # "scanner" is the default +# +# dbImage: +# registry: us.gcr.io/stackrox-scanner-db-repo +# name: scanner-db # "scanner-db" is the default +# +# +# # Customization Settings. +# # The following allows specifying custom Kubernetes metadata (labels and annotations) +# # for all objects instantiated by this Helm chart, as well as additional pod labels, +# # pod annotations, and container environment variables for workloads. +# # The configuration is hierarchical, in the sense that metadata that is defined at a more +# # generic scope (e.g., for all objects) can be overridden by metadata defined at a narrower +# # scope (e.g., only for the central deployment). +# customize: +# # Extra metadata for all objects. +# labels: +# my-label-key: my-label-value +# annotations: +# my-annotation-key: my-annotation-value +# +# # Extra pod metadata for all objects (only has an effect for workloads, i.e., deployments). +# podLabels: +# my-pod-label-key: my-pod-label-value +# podAnnotations: +# my-pod-annotation-key: my-pod-annotation-value +# +# # Extra environment variables for all containers in all objects. +# envVars: +# MY_ENV_VAR_NAME: MY_ENV_VAR_VALUE +# +# # Extra metadata for the central deployment only. +# central: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the central db deployment only. +# db: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the scanner deployment only. +# scanner: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the scanner-db deployment only. +# scanner-db: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for all other objects. The keys in the following map can be +# # an object name of the form "service/central-loadbalancer", or a reference to all +# # objects of a given type in the form "service/*". The values under each key +# # are the five metadata overrides (labels, annotations, podLabels, podAnnotations, envVars) +# # as specified above, though only the first two will be relevant for non-workload +# # object types. +# other: +# "service/*": +# labels: {} +# annotations: {} +# +# # EXPERT SETTINGS +# # The following settings should only be changed if you know very well what you are doing. +# # The scenarios in which these are required are generally not supported. +# +# # Set allowNonstandardNamespace=true if you are deploying into a namespace other than +# # "stackrox". This has been observed to work in some case, but is not generally supported. +# allowNonstandardNamespace: false +# +# # Set allowNonstandardReleaseName=true if you are deploying with a release name other than +# # the default "stackrox-central-services". This has been observed to work in some cases, +# # but is not generally supported. +# allowNonstandardReleaseName: false + +# monitoring: +# # Enables integration with OpenShift platform monitoring. +# openshift: +# enabled: true diff --git a/4.3.8/central-services/values.yaml b/4.3.8/central-services/values.yaml new file mode 100644 index 0000000..cee8132 --- /dev/null +++ b/4.3.8/central-services/values.yaml @@ -0,0 +1,364 @@ +## StackRox Central chart default settings file. +## +## This file includes the default settings for the StackRox Central chart. +## It serves as a form of documentation for all the possible settings that a +## user can override are. HOWEVER, if you want to override some settings, DO NOT +## create a copy of this file to be used as a baseline, or modify it in place. +## Instead, create a file that contains only those settings you want to override, +## and pass it to helm or roxctl via the `-f` parameter. +## +## For example, if you want to disable the deployment of scanner, create a file +## `values-override.yaml` (or any name you choose) with the following contents: +## +## scanner: +## disable: true +## +## and then invoke helm by passing `-f values-override.yaml` to +## `helm install`/`helm upgrade`. +## +## Alternatively, if you want to override just a few values, you can set them directly +## via the `--set` command, e.g., +## $ helm install --set scanner.disable=true ... +## +## Note that an arbitrary number of `-f` and `--set` parameters can be combined. It is +## generally a good practice to store secret data such as the admin password separate from +## non-sensitive configuration data. +## +# +## Configuration for image pull secrets. +## These should usually be set via the command line when running `helm install`, e.g., +## helm install --set imagePullSecrets.username=myuser --set imagePullSecrets.password=mypass, +## or be stored in a separate YAML-encoded secrets file. +#imagePullSecrets: +# # Username and password to be used for pulling images. +# # These should usually be set via the command line when running `helm install`, e.g., +# # helm install --set imagePullSecrets.username=myuser --set imagePullSecrets.password=mypass, +# # or be stored in a separate YAML-encoded secrets file. +# username: null +# password: null +# +# # If no image pull secrets are provided, an installation would usually fail. In order to +# # prevent it from failing, this option must explicitly be set to true. +# allowNone: false +# +# # If there exist available image pull secrets in the cluster that are managed separately, +# # set this value to the list of the respective secret names. While it is recommended to +# # record the secret names in a persisted YAML file, providing a single string containing +# # a comma-delimited list of secret names is also supported, for easier interaction with +# # --set. +# useExisting: [] +# +# # Whether to import any secrets from the default service account existing in the StackRox +# # namespace. The default service account often contains "standard" image pull secrets that +# # should be used by default for image pulls, hence this defaults to true. Only has an effect +# # if server-side lookups are enabled. +# useFromDefaultServiceAccount: true +# +## Common settings for all image properties +#image: +# # The image registry to use. Unless overridden in the more specific configs, this +# # determines the base registry for each image referenced in this config file. +# registry: stackrox.io +# +## Settings regarding the installation environment +#env: +# # Treat the environment as an OpenShift cluster. Leave this unset to use auto-detection +# # based on available API resources on the server. +# # Possible values: null, false, true, 3, 4 +# openshift: null +# +# # Treat the environment as Istio-enabled. Leave this unset to use auto-detection based on +# # available API resources on the server. +# # Possible values: null, false, true +# istio: null +# +# # The cloud provider platform where the target Kubernetes cluster is running. Leave this +# # unset to use auto-detection based on the Kubernetes version. +# # Possible values: null, "default", "gke" +# platform: null +# +# # Whether to run StackRox in offline mode. When run in offline mode, no connections to external +# # endpoints will be made. +# offlineMode: false +# +# # The proxy configuration for Central and Scanner, specified either as an embedded YAML +# # directionary, or as an (expandable) string. +# proxyConfig: null +# +# +## Settings for the StackRox Service CA certificates. +## If `cert` and `key` are both set (it is an error to set only one of the two), the corresponding +## values are used as the PEM-encoded certificate and private key for the internal Service CA. +## If they are left unspecified, they are generated under the following conditions: +## - `generate` is explicitly set to true, or +## - `generate` is unset (null), and the Helm chart is being freshly installed (as opposed to being +## upgraded). +#ca: +# cert: null +# key: null +# generate: null +# + +## Additional CA certificates to trust, besides system roots +## If specified, this should be a map mapping file names to PEM-encoded contents. +#additionalCAs: null +# +central: +# # Settings for telemetry data collection. + telemetry: + enabled: false + storage: + endpoint: "" + key: "" +# +# +# config: "@config/central/config.yaml|config/central/config.yaml.default" +# +# endpointsConfig: "@config/central/endpoints.yaml|config/central/endpoints.yaml.default" +# +# +# nodeSelector: null +# +# jwtSigner: +# key: null +# generate: null +# +# # Settings for the internal service-to-service TLS certificate used by central. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# defaultTLS: +# cert: null +# key: null +# +# image: +# registry: null +# name: main +# tag: 4.0.0 +# fullRef: null +# +# adminPassword: +# value: null +# generate: null +# htpasswd: null +# +# resources: +# requests: +# memory: "4Gi" +# cpu: "1500m" +# limits: +# memory: "8Gi" +# cpu: "4000m" +# +# persistence: +# hostPath: null +# persistentVolumeClaim: +# claimName: null +# createClaim: null +# storageClass: null +# size: null +# none: null +# +# exposure: +# +# # LoadBalancer configuration. +# # Disabled by default. +# # Default port is 443. +# loadBalancer: +# enabled: null +# port: null +# ip: null +# +# # NodePort configuration. +# # Disabled by default. +# nodePort: +# enabled: null +# port: null +# +# # Route configuration. +# # Disabled by default. +# route: +# enabled: null +# # Specify a custom hostname if desired, otherwise accept the default from OpenShift. +# host: null +# +# db: +# # External signifies that a Postgres wire-compatible database has already been deployed and a Central DB pod +# # does not need to be deployed +# external: false +# +# source: +# # ConnectionString should not be specified if the Central DB deployment is being managed by the helm chart +# # The connection string must be in the format described here https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING +# # client_encoding=UTF8 is required in any connection string and the only supported encoding +# # statementTimeoutMs is ignored for external database connections +# # If using a connection that supports "statement_timeout" it is recommended to include "statement_timeout=1200000" +# # Do NOT use a connection string with a password field. Instead specify the value below in the password section/ +# connectionString: null +# minConns: 10 +# maxConns: 90 +# statementTimeoutMs: 1200000 +# +# # The admin password setting for communication with Central's DB. +# # When a value is set explicitly, this is always used, even on upgrade. +# # Otherwise, a password will be automatically generated if `generate` is set to true, +# # or left unset (null) and the Helm chart is being installed (as opposed to upgraded). +# # Should only be used when utilizing Postgres as central's DB +# password: +# value: null +# generate: null +# +# postgresConfig: "@config/centraldb/postgresql.conf|config/centraldb/postgresql.conf.default" +# hbaConfig: "@config/centraldb/pg_hba.conf|config/centraldb/pg_hba.conf.default" +# +# # Specifying configOverride mounts the specified config map in the same namespace which must contain +# # both pg_hba.conf and postgresql.conf. This should only be used when the default settings are not +# # sufficient and manual override is required. +# configOverride: null +# +# nodeSelector: null +# +# # Settings for the internal service-to-service TLS certificate used by central. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# image: +# registry: null +# name: central-db +# tag: 4.0.0 +# fullRef: null +# +# resources: +# requests: +# memory: "8Gi" +# cpu: "4" +# limits: +# memory: "16Gi" +# cpu: "8" +# +# persistence: +# hostPath: null +# persistentVolumeClaim: +# claimName: null +# createClaim: null +# storageClass: null +# size: null +# none: null +# +## Configuration options relating to StackRox Scanner. +#scanner: +# # If this is set to true, StackRox will be deployed without scanner. No other setting in this +# # section will have any effect. +# disable: false +# +# # Default number of scanner replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 3 +# +# logLevel: INFO +# +# # Settings related to autoscaling the scanner deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any effect. +# disable: false +# minReplicas: 1 +# maxReplicas: 5 +# +# # Resource settings for the scanner deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "4Gi" +# cpu: "2000m" +# +# image: +# registry: null +# name: scanner +# tag: 2.3.2 +# fullRef: null +# +# dbImage: +# registry: null +# name: scanner-db +# tag: 2.3.2 +# fullRef: null +# +# # Resource settings for the scanner-db deployment. +# dbResources: +# limits: +# cpu: 2 +# memory: 4Gi +# requests: +# cpu: 200m +# memory: 200Mi +# +# # The admin password setting for communication with scanner's DB. +# # When a value is set explicitly, this is always used, even on upgrade. +# # Otherwise, a password will be automatically generated if `generate` is set to true, +# # or left unset (null) and the Helm chart is being installed (as opposed to upgraded). +# dbPassword: +# value: null +# generate: null +# +# # Settings for the internal service-to-service TLS certificate used by scanner. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# # Settings for the internal service-to-service TLS certificate used by scanner-db. +# # See the documentation for `ca` at the top level for an explanation. +# dbServiceTLS: +# cert: null +# key: null +# generate: null +# +## EXPERT SETTINGS. You usually do not need to touch those. +# +## If set to true, allow deploying in a namespace other than "stackrox". This is unsupported, so +## use at your own risk. +#allowNonstandardNamespace: false +# +## If set to true, allow a release name other than "stackrox-central-services". There are no issues +## with that, but for streamlining purposes, we want to encourage all users to stick with the +## default name, and make it a little harder to deviate from that. +#allowNonstandardReleaseName: false +# +#meta: +# # This controls whether the built-in `lookup` function will be used. If you see an error +# # about there being no function `lookup`, set this to `false` (might be required on Helm +# # versions before 3.1). +# useLookup: true +# +# # This is a dictionary from file names to contents that can be used to inject files that +# # would usually be included via .Files.Get into the chart rendering. +# fileOverrides: {} +# +# # This configuration section allows overriding settings that would be inferred from the +# # running API server. +# apiServer: +# # The Kubernetes version running on the API server. This is used for auto-detection +# # of the platform. +# version: null +# # The list of available API resources on the server, in the form of "apps/v1" or +# # "apps/v1/Deployment". This is used to detect environment capabilities. +# overrideAPIResources: null +# # A list of extra API resources that should be assumed to exist on the API server. This +# # can be used in conjunction with both data obtained from the API server, or data set +# # via `overrideAPIResources`. +# extraAPIResources: [] +# +#monitoring: +# # Enables integration with OpenShift platform monitoring. +# openshift: +# enabled: true diff --git a/4.3.8/secured-cluster-services/.helmignore b/4.3.8/secured-cluster-services/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/4.3.8/secured-cluster-services/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/4.3.8/secured-cluster-services/Chart.yaml b/4.3.8/secured-cluster-services/Chart.yaml new file mode 100644 index 0000000..bd8aec9 --- /dev/null +++ b/4.3.8/secured-cluster-services/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: stackrox-secured-cluster-services +icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/Red_Hat-Hat_icon.png +description: Helm Chart for StackRox Secured Clusters +type: application +version: 400.3.8 +appVersion: 4.3.8 diff --git a/4.3.8/secured-cluster-services/README.md b/4.3.8/secured-cluster-services/README.md new file mode 100644 index 0000000..29731e0 --- /dev/null +++ b/4.3.8/secured-cluster-services/README.md @@ -0,0 +1,468 @@ +# StackRox Kubernetes Security Platform - Secured Cluster Services Helm Chart + +This Helm chart allows you to deploy the necessary services on a StackRox +secured cluster: StackRox Sensor, StackRox Collector, and StackRox Admission +Control. +If you want to install Secured Cluster Services for Red Hat Advanced Cluster Security, +refer to [Installing the secured-cluster-services Helm chart](https://docs.openshift.com/acs/installing/installing_helm/install-helm-quick.html#installing-secured-cluster-services-quickly_acs-install-helm-quick). + +## Prerequisites + +To deploy the secured cluster services for the StackRox Kubernetes Security Platform, you must: +- Have at least version 3.1 of the Helm tool installed on your machine + +> **IMPORTANT** +> +> We publish new Helm charts with every new release of the StackRox Kubernetes +> Security Platform. Make sure to use a version of this chart that matches the +> StackRox Kubernetes Security Platform version you have installed. + +## Add the canonical chart location as a Helm repository + +The canonical repository for StackRox Helm charts is https://charts.stackrox.io. +To use StackRox Helm charts, run the following command: +```sh +helm repo add stackrox https://charts.stackrox.io +``` +Only run this command once per machine on which you want to use StackRox Helm +charts. + +Before you deploy or upgrade a chart from a remote repository, you must +run the following command: +```sh +helm repo update +``` + +## Install Secured Cluster Services + +Installing a new StackRox secured cluster requires a *cluster init bundle*. You +can generate a **cluster init bundle** by using the `roxctl` CLI or the StackRox +portal. You can use the same bundle to set up multiple StackRox secured +clusters by providing it as an input to the `helm install` command. + +> **NOTE**: +> +> - The following sections assume that you have a safe way to pass secrets to +> the helm command. +> - If not, you can decouple secret creation from installing or upgrading the +> Helm chart, see [Deployment with pre-created secrets](#deployment-with-pre-created-secrets) for more information. + +### Generate cluster init bundle + +Run the following command to generate a **cluster init bundle**: +```sh +roxctl central init-bundles generate --output cluster-init-bundle.yaml +``` + +- This command creates a **cluster init bundle** called + `cluster-init-bundle.yaml`. +- Make sure that you store this bundle securely as it contains secrets. You can + use the same bundle to set up multiple StackRox secured clusters. + +### Deploy Secured Cluster Services + +You can use the following command to deploy secured cluster services by using +this Helm chart: +```sh +helm install -n stackrox --create-namespace \ + stackrox-secured-cluster-services stackrox/stackrox-secured-cluster-services \ + -f \ + --set clusterName= \ + --set centralEndpoint= +``` +- In this command, you can replace the chart name + `stackrox/stackrox-secured-cluster-services` with the chart's file path if you have it + locally. +- The provided cluster name can either denote the intended name for a new secured cluster + or the name of an existing cluster, in which case the name will be reused and associated + with the Kubernetes cluster on which the chart is installed. + +After you deploy the StackRox Kubernetes Security Platform Secured Cluster +Services using the `helm install` command, you will see informative notes and +warnings related to the installation. The new cluster automatically registers +itself to StackRox Central, and it is visible in the StackRox portal as a +Helm-managed cluster. If the provided cluster name is already associated with +an existing secured cluster, the name will be reused and associated with the +cluster on which the chart is installed. + +In case you use image mirroring or otherwise access StackRox container images from non-standard location, +you may also need to provide image pull credentials. +There are several ways to inject the required credentials (if any) into the installation process: + +- **Explicitly specify username and password:** Use this if you are using a registry that supports username/password + authentication. Pass the following arguments to the `helm install` command: + ```sh + --set imagePullSecrets.username= --set imagePullSecrets.password= + ``` +- **Use pre-existing image pull secrets:** If you already have one or several image pull secrets + created in the namespace to which you are deploying, you can reference these in the following + way (we assume that your secrets are called `pull-secret-1` and `pull-secret-2`): + ```sh + --set imagePullSecrets.useExisting="pull-secret-1;pull-secret-2" + ``` +- **Do not use image pull secrets:** If you are pulling your images from quay.io/stackrox-io or a registry in a private + network that does not require authentication, or if the default service account in the namespace + to which you are deploying is already configured with appropriate image pull secrets, you do + not need to specify any additional image pull secrets. + +### Applying custom configuration options + +The secured cluster services Helm chart has many different configuration +options. You can directly specify these options when you run the `helm install` +command for simple use cases. + +However, we recommend storing your configuration in a file and using that file +for future upgrades or reconfiguration using the `helm upgrade` command. + +#### Specifying options with `--set` parameter + +You can use the `--set` and `--set-file` parameter with the `helm install` +command to specify various options to customize deployments quickly. However, +don't use them for specifying complex configurations. + +For example, +- **Configure cluster environment**: + ```sh + --set env.openshift=true + ``` +- **Configure collection method**: + ```sh + --set collector.collectionMethod=EBPF + ``` + +#### Using configuration YAML files and the `-f` command-line option + +We recommended that you store all custom configuration options in persisted files. + +The Secured Cluster Services Helm chart contains example configuration files +(called `values-public.yaml.example` and `values-private.yaml.example`), that list +all the available configuration options, along with documentation. + +The following sample configuration file (`secured-cluster.yaml`) uses a few of +the options which you can configure: +- **`values-public.yaml`:** + ```yaml + clusterName: "acme-cluster-01" + centralEndpoint: "central.acme-labs.internal" + + env: + istio: true # enable istio support + + sensor: + # Use custom resource overrides for sensor + resources: + requests: + cpu: "2" + memory: "4Gi" + limits: + cpu: "4" + memory: "8Gi" + + admissionControl: + dynamic: + disableBypass: true # Disable bypassing of Admission Controller + + customize: + # Apply the important-service=true label for all objects managed by this chart. + labels: + important-service: true + # Set the CLUSTER=important-cluster environment variable for all containers in the + # collector deployment: + collector: + envVars: + CLUSTER: important-cluster + ``` +- **`values-private.yaml`**: + ```yaml + imagePullSecrets: + username: + password: + ``` + +After you have created these YAML files, you can inject the configuration options into the +installation process via the `-f` flag, i.e., by appending the following options to the +`helm install` invocation: +```sh +helm install ... -f values-public.yaml -f values-private.yaml +``` + +#### Changing configuration options after deployment + +To make changes to the configuration of an existing deployment of the StackRox +Secured Cluster Services: +1. Change the configuration options in your YAML configuration file(s). +1. Use the `-f` option and specify the configuration file's path when you + run the `helm upgrade` command. + +For example, to apply configuration changes for the secured cluster, use the following command: +```sh +helm upgrade -n stackrox \ + stackrox-secured-cluster-services stackrox/stackrox-secured-cluster-services \ + --reuse-values \ + -f values-public.yaml \ + -f values-private.yaml +``` + +You can also specify configuration values using the `--set` or `--set-file` +parameters. However, these options aren't saved, and you'll have to specify all +the options again manually. + +#### Changing cluster name after deployment + +To change the name of the cluster shown in the StackRox portal, you must specify +values for both the `--clusterName` and the `--confirmNewClusterName` options: + +```sh +helm upgrade -n stackrox stackrox-secured-cluster-services --clusterName= --confirmNewClusterName= +``` + +> **NOTE:** +> +> When you change the cluster name: +> - The StackRox Kubernetes Security Platform either creates a new cluster or +> reuses an existing cluster if a cluster with the same name already exists. +> - The StackRox Kubernetes Security Platform doesn't rename the old cluster. +> The old cluster still shows up in the StackRox portal, but it doesn't +> receive any data. You must remove the old cluster if you don't want to see +> it in the StackRox portal. + +### Configuration + +The following table lists some common configuration parameters of this Helm +chart and their default values: + +|Parameter |Description | Default value | +|:---------|:-----------|:--------------| +|`clusterName`| Name of your cluster. | | +|`confirmNewClusterName`| You don't need to change this unless you upgrade and change the value for `clusterName`. In this case, set it to the new value of `clusterName`. This option exists to prevent you from [accidentally creating a new cluster with a different name](#changing-cluster-after-deployment). | `null` | +|`centralEndpoint`| Address of the Central endpoint, including the port number (without a trailing slash). If you are using a non-gRPC capable LoadBalancer, use the WebSocket protocol by prefixing the endpoint address with `wss://`. |`central.stackrox.svc:443` | +|`clusterLabels`| Custom labels associated with a secured cluster | `{}` | +|`additionalCAs`| Use it to add (named) PEM-encoded CA certificates for Sensor. | `{}` | +|`imagePullSecrets.username`| Specify username for accessing image registry. |`null`| +|`imagePullSecrets.password`| Specify password for accessing image registry. |`null`| +|`imagePullSecrets.useExisting`| Specify existing Kubernetes image pull secrets that should be used for trying to pull StackRox images. |`[]`| +|`imagePullSecrets.useFromDefaultServiceAccount`| This setting controls whether image pull secrets from a default service account in the target namespace should be used for image pulls. |`true`| +|`imagePullSecrets.useExisting`| Specify existing Kubernetes image pull secrets that should be used for trying to pull StackRox images. |`[]`| +|`imagePullSecrets.allowNone`| Enabling this setting indicates that no image pull secrets are required to be configured upon initial deployment. Use this setting if you are using a cluster-private registry that does not require authentication. |`false`| +|`image.main.name`|Repository from which to download the main image. |`main` | +|`image.collector.name`|Repository from which to download the collector image. |`collector` | +|`image.main.registry`| Address of the registry you are using for main image.|`stackrox.io` | +|`image.collector.registry`| Address of the registry you are using for collector image.|`collector.stackrox.io` | +|`sensor.endpoint`| Address of the Sensor endpoint including port number. No trailing slash.|`sensor.stackrox.svc:443` | +|`collector.collectionMethod`|Either `EBPF`, `CORE_BPF`, or `NO_COLLECTION`. |`EBPF` | +|`collector.disableTaintTolerations`|If you specify `false`, tolerations are applied to collector, and the collector pods can schedule onto all nodes with taints. If you specify it as `true`, no tolerations are applied, and the collector pods won't scheduled onto nodes with taints. |`false` | +|`collector.slimMode`| Specify `true` if you want to use a slim Collector image for deploying Collector. Using slim Collector images requires Central to provide the matching kernel module or eBPF probe. If you are running the StackRox Kubernetes Security Platform in offline mode, you must download a kernel support package from [stackrox.io](https://install.stackrox.io/collector/support-packages/index.html) and upload it to Central for slim Collectors to function. Otherwise, you must ensure that Central can access the online probe repository hosted at https://collector-modules.stackrox.io/.|`false` | +|`admissionControl.listenOnCreates`| This setting controls whether the cluster is configured to contact the StackRox Kubernetes Security Platform with `AdmissionReview` requests for `create` events on Kubernetes objects. |`false` | +|`admissionControl.listenOnUpdates`|This setting controls whether the cluster is configured to contact the StackRox Kubernetes Security Platform with `AdmissionReview` requests for `update` events on Kubernetes objects.|`false` | +|`admissionControl.listenOnEvents`|This setting controls whether the cluster is configured to contact the StackRox Kubernetes Security Platform with `AdmissionReview` requests for `update` Kubernetes events like `exec` and `portforward`.|`false` on OpenShift, `true` otherwise.| +|`admissionControl.dynamic.enforceOnCreates`| It controls whether the StackRox Kubernetes Security Platform evaluates policies; if it’s disabled, all `AdmissionReview` requests are automatically accepted. You must specify `listenOnCreates` as `true` for this to work. |`false` | +|`admissionControl.dynamic.enforceOnUpdates`| It controls whether the StackRox Kubernetes Security Platform evaluates policies for object updates; if it’s disabled, all `AdmissionReview` requests are automatically accepted. You must specify `listenOnUpdates` as `true` for this to work. |`false`| +|`admissionControl.dynamic.scanInline`| |`false` | +|`admissionControl.dynamic.disableBypass`|Set it to `true` to disable [bypassing the admission controller](https://help.stackrox.com/docs/manage-security-policies/use-admission-controller-enforcement/). |`false` | +|`admissionControl.dynamic.timeout`|The maximum time in seconds, the StackRox Kubernetes Security Platform should wait while evaluating admission review requests. Use it to set request timeouts when you enable image scanning. If the image scan runs longer than the specified time, the StackRox Kubernetes Security Platform accepts the request. Other enforcement options, such as scaling the deployment to zero replicas, are still applied later if the image violates applicable policies.|`3` | +|`registryOverride`|Use this parameter to override the default `docker.io` registry. Specify the name of your registry if you are using some other registry.| | +|`createUpgraderServiceAccount`| Specify `true` to create the `sensor-upgrader` account. By default, the StackRox Kubernetes Security Platform creates a service account called `sensor-upgrader` in each secured cluster. This account is highly privileged but is only used during upgrades. If you don’t create this account, you will have to complete future upgrades manually if the Sensor doesn’t have enough permissions. See [Enable automatic upgrades for secured clusters](https://help.stackrox.com/docs/configure-stackrox/enable-automatic-upgrades/) for more information.|`false` | +|`createSecrets`| Specify `false` to skip the orchestrator secret creation for the sensor, collector, and admission controller. | `true` | +|`customize`|Modern interface for specifying custom metadata for resources, including labels, annotations and environment variables. See below for more information.|`{}`| + + +The following table lists some advanced parameters, and you'll only need them in +non-standard environments: + +|Parameter |Description | Default value | +|:---------|:-----------|:--------------| +|`image.main.tag`| Tag of `main` image to use.|`null` | +|`image.collector.tag`| Tag of `collector` image to use.| `null` | +|`image.main.pullPolicy`| Image pull policy for `main` images.|`IfNotPresent`| +|`image.collector.pullPolicy`| Image pull policy for `collector` images.| `IfNotPresent` if `slimCollector` is enabled, `Always` otherwise.| +|`sensor.resources`|Resource specification for Sensor.|See below.| +|`collector.resources`|Resource specification for Collector.|See below.| +|`collector.complianceResources`|Resource specification for Collector's Compliance container.|See below.| +|`collector.nodeScanningResources`|Resource specification for Collector's Node Inventory container.|See below.| +|`collector.nodeSelector` | Node selector for Collector pods placement. | `null` (no placement constraints) | +|`admissionControl.resources`|Resource specification for Admission Control.|See below.| +|`sensor.imagePullPolicy`| Kubernetes image pull policy for Sensor. | `IfNotPresent` | +|`sensor.nodeSelector` | Node selector for Sensor pod placement. | `null` (no placement constraints) | +|`collector.imagePullPolicy`| Kubernetes image pull policy for Collector. | `Always` when deploying in slim mode, otherwise `IfNotPresent`. | +|`collector.complianceImagePullPolicy`| Kubernetes image pull policy for Collector. | `IfNotPresent` | +|`admissionControl.imagePullPolicy`| Kubernetes image pull policy for Admission Control. | `IfNotPresent` | +|`admissionControl.nodeSelector` | Node selector for Admission Control pods placement. | `null` (no placement constraints) | +|`exposeMonitoring`| This setting controls whether the monitoring port (TCP 9090) should be exposed on the services. | `false` | +|`env.openshift`| The StackRox Kubernetes Security Platform automatically detects the OpenShift version (`3.x` or `4.x`). Use this parameter to override the automatically detected version number, for example `4`. | `null` | +|`env.istio`| This setting can be used for overwriting the auto-sensing of Istio environments. If enabled, the cluster is set up for an Istio environment. | Auto-sensed, depends on environment. | +|`scanner.disable`| Scan images stored in the cluster's local registries. This variable is only available for the OpenShift Container Platform. | `true` | + +### Default resources + +Each container's default resource settings are defined in the +`internal/defaults.yaml` file in this chart. The following table lists the YAML +paths to the respective defaults for each container that this chart deploys: + +|Container |Path in `internal/defaults.yaml` | +|:----------------|:------------------------------------------| +|Sensor |`defaults.sensor.resources` | +|Collector |`defaults.collector.resources` | +|Compliance |`defaults.collector.complianceResources` | +|NodeInventory |`defaults.collector.nodeScanningResources`| +|Admission Control|`defaults.admissionControl.resources` | + +### Customization settings + +The `customize` setting allows specifying custom Kubernetes metadata (labels and +annotations) for all objects created by this Helm chart and additional pod +labels, pod annotations, and container environment variables for workloads. + +The configuration is hierarchical, in the sense that metadata defined at a more +generic scope (for example, for all objects) can be overridden by metadata +defined at a narrower scope (for example, only for the sensor deployment). + +For example: + +``` +customize: + # Extra metadata for all objects. + labels: + my-label-key: my-label-value + annotations: + my-annotation-key: my-annotation-value + # Extra pod metadata for all objects (only has an effect for workloads, i.e., deployments and daemonsets). + podLabels: + my-pod-label-key: my-pod-label-value + podAnnotations: + my-pod-annotation-key: my-pod-annotation-value + # Extra environment variables for all containers in all workloads. + envVars: + MY_ENV_VAR_NAME: MY_ENV_VAR_VALUE + # Extra metadata for the central deployment only. + sensor: + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + envVars: {} + # Extra metadata for the collector deployment only. + collector: + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + envVars: {} + # Extra metadata for the admission-control deployment only. + admission-control: + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + envVars: {} + # Extra metadata for all other objects. The keys in the following map can be + # an object name of the form "service/sensor", or a reference to all + # objects of a given type in the form "service/*". The values under each key + # are the five metadata overrides (labels, annotations, podLabels, podAnnotations, envVars) + # as specified above, though only the first two will be relevant for non-workload + # object types. + other: + "service/*": + labels: {} + annotations: {} +``` + +## Deployment with pre-created secrets + +The init bundle that you pass to the `helm` command using the `-f` flag creates +Kubernetes secrets for TLS certificates. If you don't want Helm to manage your +Kubernetes secrets, you can deploy the Secured Cluster Services chart without +creating secrets. However, it requires that you always specify the StackRox CA +certificate while installing or upgrading the Helm chart. This certificate +doesn't need to be kept secret. + +1. **Obtain the CA certificate configuration** either through the StackRox + portal or by using the `roxctl` CLI. + - **StackRox portal**: + 1. Navigate to **Platform Configuration** > **Integrations**. + 1. Under the **Authentication Tokens** section, select **Cluster Init Bundle**. + 1. Select **Get CA Config** on the top right to download the configuration + file called `ca-config.yaml`. + - **`roxctl CLI**: + 1. Run the following command: + ```sh + roxctl central init-bundles fetch-ca --output ca-config.yaml + ``` + This command writes the CA certificate configuration in a file called + `ca-config.yaml`. +1. **Use the CA certificate configuration in your Helm installation**. When you + run the `helm install` or the `helm upgrade` command, + pass the option `-f ca-config.yaml`: + ```sh + helm install -n stackrox stackrox-secured-cluster-services stackrox/stackrox-secured-cluster-services \ + -f ca-config.yaml \ + + ``` +1. **Disable TLS secret creation**. To prevent Helm from creating Kubernetes + secrets for the StackRox service certificates, set the `createSecrets` option + to `false`. You can either specify `createSecrets` option in a YAML + configuration file (such as `values-public.yaml`) or pass it to the `helm` + command by adding the `--set createSecrets=false` option. + +### Required Kubernetes secrets + +The following list contains the Kubernetes `Secret` objects that you need to +create in the `stackrox` namespace (or the custom namespace you are using) if +you configure the Helm chart to not create TLS certificate secrets. + +- `sensor-tls` with data: + - `ca.pem`: PEM-encoded StackRox CA certificate + - `sensor-cert.pem`: PEM-encoded StackRox Sensor certificate + - `sensor-key.pem`: PEM-encoded private key for the StackRox Sensor certificate +- `collector-tls` with data: + - `ca.pem`: PEM-encoded StackRox CA certificate + - `collector-cert.pem`: PEM-encoded StackRox Collector certificate + - `collector-key.pem`: PEM-encoded private key for the StackRox Collector certificate +- `admission-control-tls` with data: + - `ca.pem`: PEM-encoded StackRox CA certificate + - `admission-control-cert.pem`: PEM-encoded StackRox Admission Control certificate + - `admission-control-key.pem`: PEM-encoded private key for the StackRox Admision Control certificate + +#### Obtaining secrets for an existing cluster + +If you upgrade from a previous Helm chart, you can create certificates specific +to a particular cluster by using the following `roxctl` CLI command: + +```sh +export ROX_API_TOKEN= +roxctl -e sensor generate-certs +``` +Running this command create a file called `cluster--tls.yaml` in +the current directory. The file contains YAML manifests for the +[required Kubernetes secrets](#required-kubernetes-secrets). + +#### Obtaining secrets for an init bundle + +If you want to deploy multiple clusters using this Helm chart and want to create +certificates that can be used to register new clusters on-the-fly, you can +obtain the contents of an init bundle in the form of Kubernetes secrets. You can +use the StackRox portal or the `roxctl` CLI for this. + +- **Using the StackRox portal**: + 1. Navigate to **Platform Configuration** > **Integrations**. + 1. Under the **Authentication Tokens** section, select **Cluster Init Bundle**. + 1. Select the add **+** icon on the top left and enter a name for the new init + bundle. + 1. Select **Generate**. + 1. Select **Download Kubernetes Secrets File** at the bottom to save the + Kubernetes manifests to a file called + `-cluster-init-secrets.yaml`. +- **Using the `roxctl` CLI**: + 1. run the following command: + ```sh + roxctl central init-bundles generate --output-secrets cluster-init-secrets.yaml + ``` + This command stores the Kubernetes secret manifests for the cluster init + certificates in a file called `cluster-init-secrets.yaml`. + +You can then use the YAML file to generate secrets through any method that you like, for example, using Sealed Secrets. + +> **NOTE** +> +> Even when you use the certificates from an init bundle, you still need to +> specify the CA certificate configuration every time you install or upgrade the +> Helm chart. diff --git a/4.3.8/secured-cluster-services/assets/Red_Hat-Hat_icon.png b/4.3.8/secured-cluster-services/assets/Red_Hat-Hat_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fae985e3b0e5cfbcd1aa58e4a5b9d99f0274d937 GIT binary patch literal 7393 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 literal 0 HcmV?d00001 diff --git a/4.3.8/secured-cluster-services/assets/StackRox_icon.png b/4.3.8/secured-cluster-services/assets/StackRox_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3c136e3990a7382e8742c9079028abe00697c82c GIT binary patch literal 13406 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 literal 0 HcmV?d00001 diff --git a/4.3.8/secured-cluster-services/config-templates/scanner/config.yaml.tpl b/4.3.8/secured-cluster-services/config-templates/scanner/config.yaml.tpl new file mode 100644 index 0000000..5efc0b9 --- /dev/null +++ b/4.3.8/secured-cluster-services/config-templates/scanner/config.yaml.tpl @@ -0,0 +1,48 @@ +{{- /* + This is the configuration file template for Scanner. + Except for in extremely rare circumstances, you DO NOT need to modify this file. + All config options that are possibly dynamic are templated out and can be modified + via `--set`/values-files specified via `-f`. + */ -}} + +# Configuration file for scanner. + +scanner: + centralEndpoint: https://central.{{ .Release.Namespace }}.svc + sensorEndpoint: https://sensor.{{ .Release.Namespace }}.svc + database: + # Database driver + type: pgsql + options: + # PostgreSQL Connection string + # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING + source: host=scanner-db.{{ .Release.Namespace }}.svc port=5432 user=postgres sslmode={{- if eq .Release.Namespace "stackrox" }}verify-full{{- else }}verify-ca{{- end }} statement_timeout=60000 + + # Number of elements kept in the cache + # Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database. + cachesize: 16384 + + api: + httpsPort: 8080 + grpcPort: 8443 + + updater: + # Frequency with which the scanner will poll for vulnerability updates. + interval: 5m + + logLevel: {{ ._rox.scanner.logLevel }} + + # The scanner intentionally avoids extracting or analyzing any files + # larger than the following default sizes to prevent DoS attacks. + # Leave these commented to use a reasonable default. + + # The max size of files in images that are extracted. + # Increasing this number increases memory pressure. + # maxExtractableFileSizeMB: 200 + # The max size of ELF executable files that are analyzed. + # Increasing this number may increase disk pressure. + # maxELFExecutableFileSizeMB: 800 + # The max size of image file reader buffer. Image file data beyond this limit are overflowed to temporary files on disk. + # maxImageFileReaderBufferSizeMB: 100 + + exposeMonitoring: false diff --git a/4.3.8/secured-cluster-services/internal/cluster-config.yaml.tpl b/4.3.8/secured-cluster-services/internal/cluster-config.yaml.tpl new file mode 100644 index 0000000..a85ddd7 --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/cluster-config.yaml.tpl @@ -0,0 +1,33 @@ +{{- if ._rox.clusterName }} +clusterName: {{ ._rox.clusterName }} +{{- end }} +managedBy: {{ ._rox.managedBy }} +notHelmManaged: {{ eq ._rox.managedBy "MANAGER_TYPE_MANUAL" }} +clusterConfig: + staticConfig: + {{- if not ._rox.env.openshift }} + type: KUBERNETES_CLUSTER + {{- else }} + type: {{ if eq (int ._rox.env.openshift) 4 -}} OPENSHIFT4_CLUSTER {{- else -}} OPENSHIFT_CLUSTER {{ end }} + {{- end }} + mainImage: {{ coalesce ._rox.image.main._abbrevImageRef ._rox.image.main.fullRef }} + collectorImage: {{ coalesce ._rox.image.collector._abbrevImageRef ._rox.image.collector.fullRef }} + centralApiEndpoint: {{ ._rox.centralEndpoint }} + collectionMethod: {{ ._rox.collector.collectionMethod | upper | replace "-" "_" }} + admissionController: {{ ._rox.admissionControl.listenOnCreates }} + admissionControllerUpdates: {{ ._rox.admissionControl.listenOnUpdates }} + admissionControllerEvents: {{ ._rox.admissionControl.listenOnEvents }} + tolerationsConfig: + disabled: {{ ._rox.collector.disableTaintTolerations }} + slimCollector: {{ ._rox.collector.slimMode }} + dynamicConfig: + disableAuditLogs: {{ ._rox.auditLogs.disableCollection | not | not }} + admissionControllerConfig: + enabled: {{ ._rox.admissionControl.dynamic.enforceOnCreates }} + timeoutSeconds: {{ ._rox.admissionControl.dynamic.timeout }} + scanInline: {{ ._rox.admissionControl.dynamic.scanInline }} + disableBypass: {{ ._rox.admissionControl.dynamic.disableBypass }} + enforceOnUpdates: {{ ._rox.admissionControl.dynamic.enforceOnUpdates }} + registryOverride: {{ ._rox.registryOverride }} + configFingerprint: {{ ._rox._configFP }} + clusterLabels: {{- toYaml ._rox.clusterLabels | nindent 4 }} diff --git a/4.3.8/secured-cluster-services/internal/compatibility-translation.yaml b/4.3.8/secured-cluster-services/internal/compatibility-translation.yaml new file mode 100644 index 0000000..4e33afc --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/compatibility-translation.yaml @@ -0,0 +1,137 @@ +# Configuration compatibility layer translation rules. +# +# This file is a YAML file describing an object following the shape of the legacy Chart configuration. +# Each leaf object is a config fragment template, that will be merged into the user-specified config when specified +# by the user. +# +# The config fragment templates may reference the values ".value" and ".rawValue", the former containing the +# JSON-encoded value of the input field, the latter containing the value as a parsed object. + +cluster: + name: | + clusterName: {{ .value }} + type: | + env: + openshift: {{ if eq .rawValue "OPENSHIFT4_CLUSTER" }} 4 {{ else }} {{ eq .rawValue "OPENSHIFT_CLUSTER" }} {{ end }} + +endpoint: + central: | + centralEndpoint: {{ .value }} + advertised: | + sensor: + endpoint: {{ .value }} + +image: + repository: + main: | + image: + main: + name: {{ .value }} + collector: | + image: + collector: + name: {{ .value }} + registry: + main: | + image: + main: + registry: {{ .value }} + collector: | + image: + collector: + registry: {{ .value }} + pullPolicy: + main: | + image: + main: + pullPolicy: {{ .value }} + collector: | + image: + collector: + pullPolicy: {{ .value }} + tag: + main: | + image: + main: + tag: {{ .value}} + collector: | + image: + collector: + tag: {{ .value }} + +config: + collectionMethod: | + collector: + collectionMethod: {{ .value }} + + dynamic: + enforce: null # bool + scanInline: null # bool + disableBypass: null # bool + timeout: null # natural number + enforceOnUpdates: null # bool + + admissionControl: + createService: | + admissionControl: + listenOnCreates: {{ .value }} + listenOnUpdates: | + admissionControl: + listenOnUpdates: {{ .value }} + listenOnEvents: | + admissionControl: + listenOnEvents: {{ .value }} + enableService: | + admissionControl: + dynamic: + enforceOnCreates: {{ .value }} + enforceOnUpdates: | + admissionControl: + dynamic: + enforceOnUpdates: {{ .value }} + scanInline: | + admissionControl: + dynamic: + scanInline: {{ .value }} + disableBypass: | + admissionControl: + dynamic: + disableBypass: {{ .value }} + timeout: | + admissionControl: + dynamic: + timeout: {{ .value }} + registryOverride: | + registryOverride: {{ .value }} + disableTaintTolerations: | + collector: + disableTaintTolerations: {{ .value }} + createUpgraderServiceAccount: | + createUpgraderServiceAccount: {{ .value }} + createSecrets: | + createSecrets: {{ .value }} + offlineMode: null # not used + slimCollector: | + collector: + slimMode: {{ .value }} + sensorResources: | + sensor: + resources: {{ .value }} + admissionControlResources: | + admissionControl: + resources: {{ .value }} + collectorResources: | + collector: + resources: {{ .value }} + complianceResources: | + collector: + complianceResources: {{ .value }} + exposeMonitoring: | + exposeMonitoring: {{ .value }} + +envVars: | + customize: + envVars: + {{- range $_, $v := .rawValue }} + {{ quote $v.name }}: {{ quote $v.value }} + {{- end }} diff --git a/4.3.8/secured-cluster-services/internal/config-shape.yaml b/4.3.8/secured-cluster-services/internal/config-shape.yaml new file mode 100644 index 0000000..57450fa --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/config-shape.yaml @@ -0,0 +1,162 @@ +clusterName: null # string +clusterLabels: null # dict +confirmNewClusterName: null # string +centralEndpoint: null # string +registryOverride: null # string +exposeMonitoring: null # bool +createUpgraderServiceAccount: null # string +helmManaged: null +createSecrets: null +additionalCAs: null # [obj] +imagePullSecrets: + username: null # string + password: null # string + allowNone: null # bool + useExisting: null # string | [string] + useFromDefaultServiceAccount: null # bool +mainImagePullSecrets: + username: null # string + password: null # string + useExisting: null # string | [string] + useFromDefaultServiceAccount: null # bool + allowNone: null # bool +collectorImagePullSecrets: + username: null # string + password: null # string + useExisting: null # string | [string] + useFromDefaultServiceAccount: null # bool + allowNone: null # bool +image: + registry: null # string + main: + registry: null # string + name: null # string + repository: null # string + tag: null # string + fullRef: null # string + pullPolicy: null # string + collector: + slim: + fullRef: null # string + full: + fullRef: null # string + registry: null # string + name: null # string + repository: null # string + tag: null # string + fullRef: null # string + pullPolicy: null # string + scanner: + registry: null # string + name: null # string + repository: null # string + tag: null # string + fullRef: null # string + scannerDb: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string +env: + openshift: null # bool | int + istio: null # bool +ca: + cert: null # string +sensor: + imagePullPolicy: null # string + endpoint: null # string + affinity: null # dict + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + exposeMonitoring: null # bool + nodeSelector: null # string | dict + tolerations: null # [dict] + localImageScanning: + # Enables the local image scanning feature in Sensor. This disabled if local image scanning should not be used to prevent + # sensor reaching out to a scanner instance. + # This setting does not relate to the scanner deployment configuration which configures whether scanner should be deployed. + enabled: null # bool +admissionControl: + listenOnCreates: null # bool + listenOnUpdates: null # bool + listenOnEvents: null # bool + dynamic: + enforceOnCreates: null # bool + scanInline: null # bool + disableBypass: null # bool + timeout: null # natural number + enforceOnUpdates: null # bool + imagePullPolicy: null # string + replicas: null # int + affinity: null # dict + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + exposeMonitoring: null # bool + nodeSelector: null # string | dict + tolerations: null # [dict] +collector: + collectionMethod: null # string + disableTaintTolerations: null # bool + slimMode: null # bool + imagePullPolicy: null # string + tolerations: null # [dict] + resources: null # string | dict + complianceImagePullPolicy: null # string + complianceResources: null # string | dict + nodeScanningResources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + exposeMonitoring: null # bool + nodeSelector: null # string | dict + disableSELinuxOptions: null # bool + seLinuxOptionsType: null # string +auditLogs: + disableCollection: null # bool +customize: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + sensor: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + admission-control: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + collector: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + other: {} # dict +allowNonstandardNamespace: null # bool +allowNonstandardReleaseName: null # bool +enableOpenShiftMonitoring: null # bool +monitoring: + openshift: + enabled: null # bool +meta: + namespaceOverride: null # bool + useLookup: null # bool + fileOverrides: {} # dict + configFingerprintOverride: null # string + apiServer: + version: null # string + overrideAPIResources: null # [string] + extraAPIResources: null # [string] +system: + createSCCs: null # bool + enablePodSecurityPolicies: null # bool diff --git a/4.3.8/secured-cluster-services/internal/defaults/00-bootstrap.yaml b/4.3.8/secured-cluster-services/internal/defaults/00-bootstrap.yaml new file mode 100644 index 0000000..846ca57 --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/defaults/00-bootstrap.yaml @@ -0,0 +1,15 @@ +# If we are being linted, magically apply settings that will not cause linting to break. +{{- if eq .Release.Name "test-release" }} +{{- include "srox.warn" (list . "You are using a release name that is reserved for tests. In order to allow linting to work, certain checks have been relaxed. If you are deploying to a real environment, we recommend that you choose a different release name.") }} +allowNonstandardNamespace: true +allowNonstandardReleaseName: true +clusterName: test-cluster-for-lint +{{- end }} +--- + +_namespace: {{ default .Release.Namespace ._rox.meta.namespaceOverride }} + +--- +meta: + useLookup: true + fileOverrides: {} diff --git a/4.3.8/secured-cluster-services/internal/defaults/10-env.yaml b/4.3.8/secured-cluster-services/internal/defaults/10-env.yaml new file mode 100644 index 0000000..48605ae --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/defaults/10-env.yaml @@ -0,0 +1,11 @@ +# This file applies default environment configuration, based on available API server resources. +{{- if kindIs "invalid" ._rox.env.istio }} +env: + {{- if has "networking.istio.io/v1alpha3" ._rox._apiServer.apiResources }} + istio: true + {{- include "srox.note" (list . "Based on API server properties, we have inferred that you are deploying into an Istio-enabled cluster. Set the `env.istio` property explicitly to false/true to override the auto-sensed value.") }} + {{- else }} + istio: false + {{- end }} +{{- end }} +system: diff --git a/4.3.8/secured-cluster-services/internal/defaults/20-tls-files.yaml b/4.3.8/secured-cluster-services/internal/defaults/20-tls-files.yaml new file mode 100644 index 0000000..6eb6408 --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/defaults/20-tls-files.yaml @@ -0,0 +1,23 @@ +# These defaults ensure that by default, certificates and keys are loaded from the respective files in the secrets/ +# directory that they needed to be placed in for the old sensor Helm chart. +# +# A user can specify either references to files (with a "@" prefix - note that this requires changing the chart, +# as Helm only allows accessing files that are part of the chart), or PEM-encoded certificates and keys directly. + +ca: + cert: "@?secrets/ca.pem" + +sensor: + serviceTLS: + cert: "@?secrets/sensor-cert.pem" + key: "@?secrets/sensor-key.pem" + +admissionControl: + serviceTLS: + cert: "@?secrets/admission-control-cert.pem" + key: "@?secrets/admission-control-key.pem" + +collector: + serviceTLS: + cert: "@?secrets/collector-cert.pem" + key: "@?secrets/collector-key.pem" diff --git a/4.3.8/secured-cluster-services/internal/defaults/30-base-config.yaml b/4.3.8/secured-cluster-services/internal/defaults/30-base-config.yaml new file mode 100644 index 0000000..f1b86f2 --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/defaults/30-base-config.yaml @@ -0,0 +1,117 @@ +# This file contains basic configuration options for all services + +centralEndpoint: "central.{{ required "unknown namespace" ._rox._namespace }}.svc:443" +createUpgraderServiceAccount: false + +{{- if .Release.IsInstall }} +createSecrets: true +{{- end }} + +exposeMonitoring: false + +helmManaged: true + + +managedBy: MANAGER_TYPE_HELM_CHART + + +clusterName: "" +confirmNewClusterName: "" + +imagePullSecrets: + allowNone: false + useExisting: [] + useFromDefaultServiceAccount: true + +sensor: + endpoint: "sensor.{{ required "unknown namespace" ._rox._namespace }}.svc:443" + localImageScanning: + enabled: false + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Sensor is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + +admissionControl: + listenOnCreates: false + listenOnUpdates: false + listenOnEvents: {{ not ._rox.env.openshift }} + dynamic: + enforceOnCreates: false + scanInline: false + disableBypass: false + timeout: 20 + enforceOnUpdates: false + replicas: 3 + + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # node-role.kubernetes.io/master is replaced by node-role.kubernetes.io/control-plane from certain version + # of k8s. We apply both to be compatible with any k8s version. + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: Exists + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 60 + podAffinityTerm: + topologyKey: "kubernetes.io/hostname" + labelSelector: + matchLabels: + app: admission-control + +collector: + collectionMethod: "EBPF" + disableTaintTolerations: false + nodescanningEndpoint: "127.0.0.1:8444" + tolerations: + - operator: "Exists" + +auditLogs: + disableCollection: {{ ne ._rox.env.openshift 4 }} + +enableOpenShiftMonitoring: false +--- +sensor: + exposeMonitoring: {{ ._rox.exposeMonitoring }} +collector: + exposeMonitoring: {{ ._rox.exposeMonitoring }} +admissionControl: + exposeMonitoring: {{ ._rox.exposeMonitoring }} diff --git a/4.3.8/secured-cluster-services/internal/defaults/40-resources.yaml b/4.3.8/secured-cluster-services/internal/defaults/40-resources.yaml new file mode 100644 index 0000000..4dd0c19 --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/defaults/40-resources.yaml @@ -0,0 +1,44 @@ +# This file contains the default resource requirements for the StackRox Secured Cluster services. + +sensor: + resources: + requests: + memory: "4Gi" + cpu: "2" + limits: + memory: "8Gi" + cpu: "4" + +admissionControl: + resources: + requests: + memory: "100Mi" + cpu: "50m" + limits: + memory: "500Mi" + cpu: "500m" + +collector: + resources: + requests: + memory: "320Mi" + cpu: "50m" + limits: + memory: "1Gi" + cpu: "750m" + + complianceResources: + requests: + memory: "10Mi" + cpu: "10m" + limits: + memory: "2Gi" + cpu: "1" + + nodeScanningResources: + requests: + memory: "10Mi" + cpu: "10m" + limits: + memory: "500Mi" + cpu: "1" diff --git a/4.3.8/secured-cluster-services/internal/defaults/50-images.yaml b/4.3.8/secured-cluster-services/internal/defaults/50-images.yaml new file mode 100644 index 0000000..4aa3137 --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/defaults/50-images.yaml @@ -0,0 +1,114 @@ +# This file contains the default image (registry + name + tag) settings) for all StackRox Secured Cluster +# Services. + +# Initialize default meta values +image: + registry: stackrox.io + main: + name: main + pullPolicy: IfNotPresent + collector: + name: collector + slimName: collector-slim + scanner: + name: scanner-slim + tag: 4.3.8 + + scannerDb: + name: scanner-db-slim + tag: 4.3.8 + +--- +# Add registry defaults +image: + main: + registry: {{ ._rox.image.registry }} + collector: + registry: {{ if or (eq ._rox.image.registry "stackrox.io") (eq ._rox.image.registry "registry.connect.redhat.com") }}collector.stackrox.io{{ else }}{{ ._rox.image.registry }}{{ end }} + scanner: + registry: {{ ._rox.image.registry }} + + scannerDb: + registry: {{ ._rox.image.registry }} + +--- +# Default to collector slim mode. If configured registry equals the default we can assume the cluster has internet connectivity. +collector: + slimMode: {{ eq ._rox.image.collector.registry "collector.stackrox.io" }} +--- +# Configure repository (registry + name) +image: + main: + repository: {{ list ._rox.image.main.registry ._rox.image.main.name | compact | join "/" }} + collector: + {{- if ._rox.collector.slimMode }} + repository: {{ list ._rox.image.collector.registry ._rox.image.collector.slimName | compact | join "/" }} + {{- else }} + repository: {{ list ._rox.image.collector.registry ._rox.image.collector.name | compact | join "/" }} + {{- end }} + scanner: + repository: {{ list ._rox.image.scanner.registry ._rox.image.scanner.name | compact | join "/" }} + + scannerDb: + repository: {{ list ._rox.image.scannerDb.registry ._rox.image.scannerDb.name | compact | join "/" }} + +--- +# Configure collector slim image full ref +image: + collector: + {{- if and ._rox.collector.slimMode ._rox.image.collector.slim.fullRef }} + fullRef: {{ ._rox.image.collector.slim.fullRef }} + {{- else if and (not ._rox.collector.slimMode) ._rox.image.collector.full.fullRef }} + fullRef: {{ ._rox.image.collector.full.fullRef }} + {{- end }} +--- +# Apply fullRef and configurations to images +image: + main: + {{- if or ._rox.image.main.tag ._rox.image.main.fullRef }} + {{- include "srox.warn" (list . "You have specified an explicit main image (tag). This will prevent the main image from being updated correctly when upgrading to a newer version of this chart.") }} + {{- else }} + _abbrevImageRef: {{ ._rox.image.main.repository }} + {{- end }} + tag: 4.3.8 + collector: + {{- if or ._rox.image.collector.tag ._rox.image.collector.fullRef }} + {{- include "srox.warn" (list . "You have specified an explicit collector image tag. This will prevent the collector image from being updated correctly when upgrading to a newer version of this chart.") }} + {{- if ._rox.collector.slimMode }} + {{- include "srox.warn" (list . "You have specified an explicit collector image tag. The slim collector setting will not have any effect.") }} + {{- end }} + {{- else }} + _abbrevImageRef: {{ ._rox.image.collector.repository }} + {{- end }} +--- +# Configure tags and pull policies +image: + collector: + {{- if ._rox.collector.slimMode }} + tag: "4.3.8" + pullPolicy: IfNotPresent + {{- else }} + tag: "4.3.8" + pullPolicy: Always + {{- end }} +--- +# Add fullRef references to images +# TODO(ROX-9261): Add support for image pull policy to scanner slim +image: + main: + fullRef: {{ printf "%s:%s" ._rox.image.main.repository ._rox.image.main.tag }} + collector: + fullRef: {{ printf "%s:%s" ._rox.image.collector.repository ._rox.image.collector.tag }} + scanner: + fullRef: {{ printf "%s:%s" ._rox.image.scanner.repository ._rox.image.scanner.tag }} + + scannerDb: + fullRef: {{ printf "%s:%s" ._rox.image.scannerDb.repository ._rox.image.scannerDb.tag }} + +collector: + imagePullPolicy: {{ ._rox.image.collector.pullPolicy }} + complianceImagePullPolicy: {{ ._rox.image.main.pullPolicy }} +sensor: + imagePullPolicy: {{ ._rox.image.main.pullPolicy }} +admissionControl: + imagePullPolicy: {{ ._rox.image.main.pullPolicy }} diff --git a/4.3.8/secured-cluster-services/internal/defaults/60-sccs.yaml b/4.3.8/secured-cluster-services/internal/defaults/60-sccs.yaml new file mode 100644 index 0000000..36e74fd --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/defaults/60-sccs.yaml @@ -0,0 +1,2 @@ +system: + createSCCs: true diff --git a/4.3.8/secured-cluster-services/internal/defaults/70-scanner.yaml b/4.3.8/secured-cluster-services/internal/defaults/70-scanner.yaml new file mode 100644 index 0000000..43bc5d8 --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/defaults/70-scanner.yaml @@ -0,0 +1,38 @@ +scanner: + disable: true + replicas: 3 + logLevel: INFO + mode: slim + + autoscaling: + disable: false + minReplicas: 2 + maxReplicas: 5 + + resources: + requests: + memory: "1500Mi" + cpu: "1000m" + limits: + memory: "4Gi" + cpu: "2000m" + + dbResources: + limits: + cpu: "2000m" + memory: "4Gi" + requests: + cpu: "200m" + memory: "200Mi" + + slimImage: + name: "" + tag: "" + fullRef: "" + repository: "" + + slimDBImage: + name: "" + tag: "" + fullRef: "" + repository: "" diff --git a/4.3.8/secured-cluster-services/internal/defaults/whats-this.md b/4.3.8/secured-cluster-services/internal/defaults/whats-this.md new file mode 100644 index 0000000..d58c8de --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/defaults/whats-this.md @@ -0,0 +1,39 @@ +`defaults/` directory +====================== + +This directory provides a set of files that provide a lighter-weight interface for configuring +defaults in the Helm chart, allowing the use of template expressions (including referencing previously +applied defaults) without requiring (an excessive amount of) template control structures (such as +`{{ if kindIs "invalid" ... }}` to determine if a value has already been set). + +After applying some "bootstrap" configuration (such as for making available API server resources +visible in a uniform manner), each `.yaml` file in this directory is processed in an order determined +by its name (hence the `NN-` prefixes). Each YAML file consists of multiple documents (separated by +`---` lines) that are rendered as templates and then _merged_ into the effective configuration, giving +strict preference to already set values. + +Having a deterministic order is important for being able to rely on previously configured +values (either specified by the user or applied as a default). For example, the file +```yaml +group: + setting: "foo" + anotherSetting: 3 +--- +group: + derivedSetting: {{ printf "%s-%d" ._rox.group.setting ._rox.group.anotherSetting }} +``` +combined with the command-line setting `--set group.setting=bar` will result in the following +"effective" configuration: +```yaml +group: + setting: "bar" # user-specified value takes precedence - default value "foo" not applied + anotherSetting: 3 # default value + derivedSetting: bar-3 # combination of user-specified value and default value; "pure" default without + # any --set arguments would be "foo-3" +``` + +**Caveats**: +- Templating instructions must be contained to a single document within the multi-document YAML files. In particular, + the `---` separator must not be within a conditionally rendered block, or emitted by templating code. +- It is recommended to contain dependencies between default settings to a single YAML file. While the `NN-` prefixes + ensure a well-defined application order of individual files, having dependent blocks in the same file adds clarity. diff --git a/4.3.8/secured-cluster-services/internal/expandables.yaml b/4.3.8/secured-cluster-services/internal/expandables.yaml new file mode 100644 index 0000000..09ebbae --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/expandables.yaml @@ -0,0 +1,44 @@ +imagePullSecrets: + username: true + password: true +mainImagePullSecrets: + username: true + password: true +collectorImagePullSecrets: + username: true + password: true +ca: + cert: true +sensor: + serviceTLS: + cert: true + key: true + resources: true + nodeSelector: true +admissionControl: + serviceTLS: + cert: true + key: true + resources: true + nodeSelector: true +collector: + serviceTLS: + cert: true + key: true + resources: true + complianceResources: true + nodeScanningResources: true + nodeSelector: true +scanner: + resources: true + dbResources: true + nodeSelector: true + dbNodeSelector: true + dbPassword: + value: true + serviceTLS: + cert: true + key: true + dbServiceTLS: + cert: true + key: true diff --git a/4.3.8/secured-cluster-services/internal/scanner-config-shape.yaml b/4.3.8/secured-cluster-services/internal/scanner-config-shape.yaml new file mode 100644 index 0000000..da3b315 --- /dev/null +++ b/4.3.8/secured-cluster-services/internal/scanner-config-shape.yaml @@ -0,0 +1,40 @@ +scanner: + mode: null # string + disable: null # bool + replicas: null # int + logLevel: null # string + nodeSelector: null # string | dict + dbNodeSelector: null # string | dict + tolerations: null # [dict] + dbTolerations: null # [dict] + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + affinity: null # dict + resources: null # string | dict + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + dbImage: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + dbResources: null # string | dict + dbPassword: + value: null # string + generate: null # bool + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + dbServiceTLS: + cert: null # string + key: null # string + generate: null # bool + exposeMonitoring: null # bool +system: + enablePodSecurityPolicies: null # bool diff --git a/4.3.8/secured-cluster-services/scripts/fetch-secrets.sh b/4.3.8/secured-cluster-services/scripts/fetch-secrets.sh new file mode 100755 index 0000000..850a227 --- /dev/null +++ b/4.3.8/secured-cluster-services/scripts/fetch-secrets.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# fetch-secrets.sh +# Retrieves StackRox TLS secrets currently stored in the current Kubernetes context, and stores them in a format +# suitable for consumption by the Helm chart. +# +# The YAML bundle is printed to stdout, use output redirection (>filename) to store the output to a file. +# This script supports the following environment variables: +# - KUBECTL: the command to use for kubectl. Spaces will be tokenized by the shell interpreter (default: "kubectl"). +# - ROX_NAMESPACE: the namespace in which the current StackRox deployment runs (default: "stackrox") +# - FETCH_CA_ONLY: if set to "true", will create a bundle containing only the CA certificate (default: "false") + +DIR="$(cd "$(dirname "$0")" && pwd)" + +KUBECTL="${KUBECTL:-kubectl}" +ROX_NAMESPACE="${ROX_NAMESPACE:-stackrox}" + +FETCH_CA_ONLY="${FETCH_CA_ONLY:-false}" + +case "$FETCH_CA_ONLY" in + false|0) + TEMPLATE_FILE="fetched-secrets-bundle.yaml.tpl" + DESCRIPTION="certificates and keys" + ;; + true|1) + TEMPLATE_FILE="fetched-secrets-bundle-ca-only.yaml.tpl" + DESCRIPTION="CA certificate only" + ;; + *) + echo >&2 "Invalid value '$FETCH_CA_ONLY' for FETCH_CA_ONLY, only false and true are allowed" + exit 1 +esac + +# The leading '#' signs aren't required as they don't go to stdout, but when printing to the console, +# it looks more natural to include them. +echo >&2 "# Fetching $DESCRIPTION from current Kubernetes context (namespace $ROX_NAMESPACE), store" +echo >&2 "# the output in a file and pass it to helm via the -f parameter." + +$KUBECTL get --ignore-not-found -n "$ROX_NAMESPACE" \ + secret/sensor-tls secret/collector-tls secret/admission-control-tls \ + -o go-template-file="${DIR}/${TEMPLATE_FILE}" \ diff --git a/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl b/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl new file mode 100644 index 0000000..b5a13c2 --- /dev/null +++ b/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl @@ -0,0 +1,9 @@ +{{- range $item := .items }} +{{- if eq $item.metadata.name "sensor-tls" }} +{{- $caPEM := index $item.data "ca.pem" }} +{{- if $caPEM }} +ca: + cert: "{{ $caPEM | base64decode | js }}" +{{- end }} +{{- end }} +{{- end }} diff --git a/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl b/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl new file mode 100644 index 0000000..72bb452 --- /dev/null +++ b/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl @@ -0,0 +1,35 @@ +{{- range $item := .items }} +{{- if eq $item.metadata.name "sensor-tls" }} +{{- $caPEM := index $item.data "ca.pem" }} +{{- if $caPEM }} +ca: + cert: "{{ $caPEM | base64decode | js }}" +{{- end }} +{{- $sensorCert := index $item.data "sensor-cert.pem" }} +{{- $sensorKey := index $item.data "sensor-key.pem" }} +{{- if and $sensorCert $sensorKey }} +sensor: + serviceTLS: + cert: "{{ $sensorCert | base64decode | js }}" + key: "{{ $sensorKey | base64decode | js }}" +{{- end }} +{{- else if eq $item.metadata.name "collector-tls" }} +{{- $collectorCert := index $item.data "collector-cert.pem" }} +{{- $collectorKey := index $item.data "collector-key.pem" }} +{{- if and $collectorCert $collectorKey }} +collector: + serviceTLS: + cert: "{{ $collectorCert | base64decode | js }}" + key: "{{ $collectorKey | base64decode | js }}" +{{- end }} +{{- else if eq $item.metadata.name "admission-control-tls" }} +{{- $admCtrlCert := index $item.data "admission-control-cert.pem" }} +{{- $admCtrlKey := index $item.data "admission-control-key.pem" }} +{{- if and $admCtrlCert $admCtrlKey }} +admissionControl: + serviceTLS: + cert: "{{ $admCtrlCert | base64decode | js }}" + key: "{{ $admCtrlKey | base64decode | js }}" +{{- end }} +{{- end }} +{{- end }} diff --git a/4.3.8/secured-cluster-services/sensor-chart-upgrade.md b/4.3.8/secured-cluster-services/sensor-chart-upgrade.md new file mode 100644 index 0000000..f3d5ddf --- /dev/null +++ b/4.3.8/secured-cluster-services/sensor-chart-upgrade.md @@ -0,0 +1,159 @@ +# Upgrading from the `sensor` Helm chart + +There are differences between the `sensor` Helm chart that was part of the +StackRox Kubernetes Security Platform version 3.0.54 and the Secured Cluster +Services Helm chart in the StackRox Kubernetes Security Platform version 3.0.55. + +Therefore, if you are using the StackRox Kubernetes Security Platform version 3.0.54 +or older, and you've used the `sensor` Helm chart, you must verify (and change) +the following additional options to upgrade to the new Helm charts for the +StackRox Kubernetes Security Platform version 3.0.55. + +## Namespace + +|Version 3.0.54 and older |Version 3.0.55 and newer | +|-------------------------|-------------------------| +|The `sensor` Helm chart creates all Kubernetes resources in the `stackrox` namespace, even if you've used the `-n`/`--namespace` flag to the `helm install` command.|The Secured Cluster Services Helm chart creates all resources in the namespace you specify by using the `-n`/`--namespace` flag. However, we recommend that you always install the chart in the `stackrox` namespace.| + +If you've previously installed the `sensor` Helm chart into a namespace other +than `stackrox`, you **must** set the namespace override option to `stackrox`. + +To do this, either: +- pass the `--set meta.namespaceOverride=stackrox` flag, or +- add the following section in your configuration file: + ```yaml + meta: + namespaceOverride: stackrox + ``` + +## Configuration file + +|Version 3.0.54 and older |Version 3.0.55 and newer | +|-------------------------|--------------------------| +|Installation using the `sensor` Helm chart requires adding your customizations in the `values.yaml` file that is part of the chart.|The Secured Cluster Services Helm chart uses a separate configuration file.| + +> **IMPORTANT** +> +> If you are using the Secured Cluster Services Helm chart, **do not** modify +> the `values.yaml` file that is part of the chart. + +We recommend that you always store the configuration in separate files: + +- `values-public.yaml`: include all non-sensitive configuration options in this + file. +- `values-private.yaml`: include all sensitive configuration options such as + image pull secrets or certificates and keys. + +You can also use a separate file for the cluster init bundle. For more +information, see the main [README.md](README.md) file. + +## Secrets injection + +|Version 3.0.54 and older |Version 3.0.55 and newer | +|-------------------------|--------------------------| +|The `sensor` Helm chart downloads certificates and private keys specific to a single cluster and stores them in the `secrets/` directory.|The Secured Cluster Services Helm chart uses cluster init bundles. For more information, see the main [README.md](README.md) file.| + +To upgrade, +1. Copy the `values.yaml` you used for the most recent installation or upgrade of the + `sensor` Helm chart and store it as `sensor-values.yaml`. +1. Connect to the Kubernetes cluster on which you've previously installed the + `sensor` Helm chart. +1. Run `./scripts/fetch-secrets.sh`. The `fetch-secrets.sh` script shows a YAML + file as output, which contains all secrets. Store the output of this command + in a file (you can use `./scripts/fetch-secrets.sh >secrets.yaml` to directly + write the command output to a file called `secrets.yaml`). +1. Run the `helm upgrade` command and pass the YAML (from the previous step) file by + using the `-f` option: + ```sh + helm upgrade -n stackrox sensor stackrox/secured-cluster-services \ + --reuse-values -f sensor-values.yaml -f ... + ``` + The above command assumes that you have added the https://charts.stackrox.io Helm + chart repository to your local Helm installation. See the main [README.md](README.md) + for instructions on how to set this up. + If you want to use this chart from a local directory, replace + `stackrox/secured-cluster-services` with the path to the chart directory. + +> **NOTE** +> +> Although you can copy the `secrets` directory from your old `sensor` Helm +> chart instead, we **do not** recommend doing it. + + +## Helm-managed clusters + +When you use the Secured Cluster Services Helm chart, the clusters it creates +are treated as Helm-managed by default. It means that whenever you run the +`helm upgrade` command afterward, it applies the configuration changes specified +in your Helm configuration file, overwriting any changes to settings you've done +through the StackRox portal. + +Additionally, because of the differences between the Helm upgrade and the +StackRox Kubernetes Security Platform automatic upgrade, you can't use +the automatic upgrades option from the StackRox portal. + +If you don't want an upgraded cluster to be treated as Helm-managed, set the +`helmManaged` configuration option to `false`. + +## Configuration format + +There are differences between the configuration format that the sensor Helm +chart uses and the Secured Cluster Services Helm chart's uses. We recommend that +you migrate to the new configuration format. + +Here is the list of old and new configuration options: + +|Old configuration option |New configuration option | +|-------------------------|-------------------------| +| `cluster.name` | `clusterName` | +| `cluster.type` | Set `env.openshift` to `true` for `cluster.type=OPENSHIFT_CLUSTER` and `false` for `cluster.type=KUBERNETES_CLUSTER`. Leave unset to automatically detect (recommended). | +| `endpoint.central` | `centralEndpoint` | +| `endpoint.advertised` | `sensor.endpoint` | +| `image.repository.main` | `image.main.name` | +| `image.repository.collector` | `image.collector.name` | +| `image.registry.main` | `image.main.registry` | +| `image.registry.collector` | `image.collector.registry` | +| `image.pullPolicy.main` | `image.main.pullPolicy` | +| `image.pullPolicy.collector` | `image.collector.pullPolicy` | +| `image.tag.main` | `image.main.tag` | +| `image.tag.collector` | `image.collector.tag` | +| `config.collectionMethod` | `collector.collectionMethod` | +| `config.admissionControl.createService` | `admissionControl.listenOnCreates` | +| `config.admissionControl.listenOnUpdates` | `admissionControl.listenOnUpdates` | +| `config.admissionControl.enableService` | `admissionControl.dynamic.enforceOnCreates` | +| `config.admissionControl.enforceOnUpdates` | `admissionControl.dynamic.enforceOnUpdates` | +| `config.admissionControl.scanInline` | `admissionControl.dynamic.scanInline` | +| `config.admissionControl.disableBypass` | `admissionControl.dynamic.disableBypass` | +| `config.admissionControl.timeout` | `admissionControl.dynamic.timeout` | +| `config.registryOverride` | `registryOverride` | +| `config.disableTaintTolerations` | `collector.disableTaintTolerations` | +| `config.createUpgraderServiceAccount` | `createUpgraderServiceAccount` | +| `config.createSecrets` | `createSecrets` | +| `config.offlineMode` | This option has no effect and will be removed. | +| `config.slimCollector` | `collector.slimMode` | +| `config.sensorResources` | `sensor.resources` | +| `config.admissionControlResources` | `admissionControl.resources` | +| `config.collectorResources` | `collector.resources` | +| `config.complianceResources` | `collector.complianceResources` | +| `config.exposeMonitoring` | `exposeMonitoring` | +| `envVars` | See example below | + +**Custom environment variables:** The old format for custom environment variable settings was +```yaml +envVars: +- name: ENV_VAR1 + value: "value1" +- name: ENV_VAR2 + value: "value2" +... +``` + +In the new configuration format, rewrite this as: +```yaml +customize: + envVars: + ENV_VAR1: "value1" + ENV_VAR2: "value2" +``` +You can find out more about customizing object labels, annotations, and environment variables in the main +[README.md](README.md). \ No newline at end of file diff --git a/4.3.8/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml b/4.3.8/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml new file mode 100644 index 0000000..eba103f --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.collectorImagePullSecrets._dockerAuths }} +apiVersion: v1 +kind: Secret +type: kubernetes.io/dockerconfigjson +metadata: + name: secured-cluster-services-collector + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "secured-cluster-services-collector") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "secured-cluster-services-collector") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +data: + .dockerconfigjson: {{ dict "auths" ._rox.collectorImagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/00-injected-ca-bundle.yaml b/4.3.8/secured-cluster-services/templates/00-injected-ca-bundle.yaml new file mode 100644 index 0000000..3289c2a --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/00-injected-ca-bundle.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} + +{{- if eq ._rox.env.openshift 4 }} +{{ $injectedCABundleName := printf "injected-cabundle-%s" .Release.Name }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $injectedCABundleName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" $injectedCABundleName) | nindent 4 }} + "config.openshift.io/inject-trusted-cabundle": "true" + annotations: + {{- include "srox.annotations" (list . "configmap" $injectedCABundleName) | nindent 4 }} +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/00-main-image-pull-secrets.yaml b/4.3.8/secured-cluster-services/templates/00-main-image-pull-secrets.yaml new file mode 100644 index 0000000..052aa3e --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/00-main-image-pull-secrets.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.mainImagePullSecrets._dockerAuths }} +apiVersion: v1 +kind: Secret +type: kubernetes.io/dockerconfigjson +metadata: + name: secured-cluster-services-main + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "secured-cluster-services-main") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "secured-cluster-services-main") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +data: + .dockerconfigjson: {{ dict "auths" ._rox.mainImagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml b/4.3.8/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml new file mode 100644 index 0000000..a27c602 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "scanner") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} + +{{ end -}} diff --git a/4.3.8/secured-cluster-services/templates/02-scanner-01-psps.yaml b/4.3.8/secured-cluster-services/templates/02-scanner-01-psps.yaml new file mode 100644 index 0000000..23b398c --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/02-scanner-01-psps.yaml @@ -0,0 +1,69 @@ +{{- include "srox.init" . -}} + +{{- if and (not ._rox.scanner.disable) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-scanner-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-scanner-psp") | nindent 4 }} +rules: +- apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-scanner-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-scanner-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-scanner-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-psp") }} +subjects: + - kind: ServiceAccount + name: scanner + namespace: {{ .Release.Namespace }} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-scanner") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/02-scanner-01-security.yaml b/4.3.8/secured-cluster-services/templates/02-scanner-01-security.yaml new file mode 100644 index 0000000..3c1d92b --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/02-scanner-01-security.yaml @@ -0,0 +1,78 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable }} +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-scanner") | nindent 4 }} + kubernetes.io/description: stackrox-scanner is the security constraint for the Scanner container +priority: 0 +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +users: + - system:serviceaccount:{{ .Release.Namespace }}:scanner +volumes: + - '*' +allowHostDirVolumePlugin: false +allowedCapabilities: [] +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +defaultAddCapabilities: [] +fsGroup: + type: RunAsAny +readOnlyRootFilesystem: false +requiredDropCapabilities: [] + +{{- else if eq ._rox.env.openshift 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-scanner-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-scanner-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-scanner-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - anyuid + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: scanner-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "scanner-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "scanner-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-scanner-scc +subjects: +- kind: ServiceAccount + name: scanner + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml b/4.3.8/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml new file mode 100644 index 0000000..c6c0bc1 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml @@ -0,0 +1,27 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if ._rox.scanner._dbPassword -}} +{{- if not (kindIs "invalid" ._rox.scanner._dbPassword.value) -}} + +apiVersion: v1 +kind: Secret +metadata: + name: scanner-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.scanner._dbPassword.value | nindent 4 }} + +{{- end -}} +{{- end -}} + +{{ end -}} diff --git a/4.3.8/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml b/4.3.8/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml new file mode 100644 index 0000000..4ed16c7 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner/config.yaml.tpl") . | nindent 4 }} + +{{ end -}} diff --git a/4.3.8/secured-cluster-services/templates/02-scanner-05-network-policy.yaml b/4.3.8/secured-cluster-services/templates/02-scanner-05-network-policy.yaml new file mode 100644 index 0000000..99f7233 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/02-scanner-05-network-policy.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner + ingress: + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP +{{ if or (eq ._rox.scanner.mode "slim") ._rox.env.openshift }} + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP +{{ end }} + policyTypes: + - Ingress + +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-db") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-db + ingress: + - from: + - podSelector: + matchLabels: + app: scanner + ports: + - port: 5432 + protocol: TCP + policyTypes: + - Ingress + +{{ end -}} + +{{ if ._rox.scanner.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: scanner + policyTypes: + - Ingress +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/02-scanner-06-deployment.yaml b/4.3.8/secured-cluster-services/templates/02-scanner-06-deployment.yaml new file mode 100644 index 0000000..89ac82c --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/02-scanner-06-deployment.yaml @@ -0,0 +1,296 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + app: scanner + {{- include "srox.labels" (list . "deployment" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner") | nindent 4 }} +spec: + replicas: {{ ._rox.scanner.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner + {{- include "srox.podLabels" (list . "deployment" "scanner") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8080,8443" + {{- include "srox.podAnnotations" (list . "deployment" "scanner") | nindent 8 }} + spec: + {{- if ._rox.scanner._nodeSelector }} + nodeSelector: + {{- ._rox.scanner._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.tolerations }} + tolerations: + {{- toYaml ._rox.scanner.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scanner.affinity | nindent 8 }} + containers: + - name: scanner + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimImage.fullRef | quote }} + {{ else }} + image: {{ ._rox.scanner.image.fullRef | quote }} + {{ end -}} + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if ._rox.env.openshift }} + - name: ROX_OPENSHIFT_API + value: "true" + {{- end}} + {{- include "srox.envVars" (list . "deployment" "scanner" "scanner") | nindent 8 }} + resources: + {{- ._rox.scanner._resources | nindent 10 }} + command: + - /entrypoint.sh + ports: + - name: https + containerPort: 8080 + - name: grpc + containerPort: 8443 + {{ if ._rox.scanner.exposeMonitoring -}} + - name: monitoring + containerPort: 9090 + {{- end}} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /scanner/ping + port: 8080 + timeoutSeconds: 10 + periodSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + volumeMounts: + - name: scanner-etc-ssl-volume + mountPath: /etc/ssl + - name: scanner-etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: scanner-config-volume + mountPath: /etc/scanner + readOnly: true + - name: scanner-tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: vuln-temp-db + mountPath: /var/lib/stackrox + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: scanner-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner + volumes: + - name: additional-ca-volume + secret: + defaultMode: 420 + optional: true + secretName: additional-ca + - name: scanner-etc-ssl-volume + emptyDir: {} + - name: scanner-etc-pki-volume + emptyDir: {} + - name: scanner-config-volume + configMap: + name: scanner-config + - name: scanner-tls-volume + secret: + secretName: scanner-tls + - name: vuln-temp-db + emptyDir: {} + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: scanner-db-password + secret: + secretName: scanner-db-password + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + app: scanner-db + {{- include "srox.labels" (list . "deployment" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-db + {{- include "srox.podLabels" (list . "deployment" "scanner-db") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "5432" + {{- include "srox.podAnnotations" (list . "deployment" "scanner-db") | nindent 8 }} + spec: + {{- if ._rox.scanner._dbNodeSelector }} + nodeSelector: + {{- ._rox.scanner._dbNodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.dbTolerations }} + tolerations: + {{- toYaml ._rox.scanner.dbTolerations | nindent 8 }} + {{- end }} + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # ScannerDB is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + initContainers: + - name: init-db + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimDBImage.fullRef | quote }} + {{ else -}} + image: {{ ._rox.scanner.dbImage.fullRef | quote }} + {{ end -}} + env: + - name: POSTGRES_PASSWORD_FILE + value: "/run/secrets/stackrox.io/secrets/password" + - name: ROX_SCANNER_DB_INIT + value: "true" + resources: + {{- ._rox.scanner._dbResources | nindent 12 }} + volumeMounts: + - name: scanner-db-data + mountPath: /var/lib/postgresql/data + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + readOnly: true + - name: scanner-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + containers: + - name: db + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimDBImage.fullRef | quote }} + {{ else -}} + image: {{ ._rox.scanner.dbImage.fullRef | quote }} + {{ end -}} + env: + {{- include "srox.envVars" (list . "deployment" "scanner-db" "db") | nindent 10 }} + ports: + - name: tcp-postgresql + protocol: TCP + containerPort: 5432 + resources: + {{- ._rox.scanner._dbResources | nindent 10 }} + volumeMounts: + - name: scanner-db-data + mountPath: /var/lib/postgresql/data + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + readOnly: true + serviceAccountName: scanner + securityContext: + fsGroup: 70 + runAsGroup: 70 + runAsNonRoot: true + runAsUser: 70 + volumes: + - name: scanner-config-volume + configMap: + name: scanner-config + - name: scanner-tls-volume + secret: + secretName: scanner-tls + - name: scanner-db-tls-volume + secret: + secretName: scanner-db-tls + defaultMode: 0640 + items: + - key: cert.pem + path: server.crt + - key: key.pem + path: server.key + - key: ca.pem + path: root.crt + - name: scanner-db-data + emptyDir: {} + - name: scanner-db-password + secret: + secretName: scanner-db-password + +{{ end -}} diff --git a/4.3.8/secured-cluster-services/templates/02-scanner-07-service.yaml b/4.3.8/secured-cluster-services/templates/02-scanner-07-service.yaml new file mode 100644 index 0000000..2f65b15 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/02-scanner-07-service.yaml @@ -0,0 +1,99 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: Service +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner") | nindent 4 }} +spec: + ports: + - name: https-scanner + port: 8080 + targetPort: 8080 + - name: grpcs-scanner + port: 8443 + targetPort: 8443 + {{ if ._rox.scanner.exposeMonitoring -}} + - name: monitoring + port: 9090 + targetPort: monitoring + {{- end}} + selector: + app: scanner + type: ClusterIP + +--- + +apiVersion: v1 +kind: Service +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-db") | nindent 4 }} +spec: + ports: + - name: tcp-db + port: 5432 + targetPort: 5432 + selector: + app: scanner-db + type: ClusterIP + +{{ if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for ports 8080 and 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8080 + tls: + mode: DISABLE + - port: + number: 8443 + tls: + mode: DISABLE + +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-db-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-db-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 5432, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-db-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-db.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 5432 + tls: + mode: DISABLE +{{ end }} + +{{ end -}} diff --git a/4.3.8/secured-cluster-services/templates/02-scanner-08-hpa.yaml b/4.3.8/secured-cluster-services/templates/02-scanner-08-hpa.yaml new file mode 100644 index 0000000..c7af476 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/02-scanner-08-hpa.yaml @@ -0,0 +1,25 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if not ._rox.scanner.autoscaling.disable -}} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scanner.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scanner.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner + targetCPUUtilizationPercentage: 150 +{{ end -}} + +{{ end -}} diff --git a/4.3.8/secured-cluster-services/templates/NOTES.txt b/4.3.8/secured-cluster-services/templates/NOTES.txt new file mode 100644 index 0000000..9c9fd01 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/NOTES.txt @@ -0,0 +1,40 @@ +{{- $_ := include "srox.init" . -}} + +StackRox Secured Cluster Services {{.Chart.AppVersion}} has been installed. + + +Secured Cluster Configuration Summary: + + Name: {{ ._rox.clusterName }} + Kubernetes Namespace: {{ ._rox._namespace }}{{ if ne .Release.Namespace ._rox._namespace }} [NOTE: Helm release is attached to namespace {{ .Release.Namespace }}]{{ end }} + Helm Release Name: {{ .Release.Name }} + Central Endpoint: {{ ._rox.centralEndpoint }} + OpenShift Cluster: {{ if eq ._rox.env.openshift 0 -}} false {{ else -}} {{ ._rox.env.openshift }} {{ end }} + Admission Control Webhooks deployed: {{ or ._rox.admissionControl.dynamic.listenOnCreates ._rox.admissionControl.dynamic.listenOnUpdates ._rox.admissionControl.dynamic.listenOnEvents}} + Admission Control Creates/Updates enforced: {{ or ._rox.admissionControl.dynamic.enforceOnCreates ._rox.admissionControl.dynamic.enforceOnUpdates }} + +{{ if ._rox._state.notes -}} +Please take note of the following: +{{ range ._rox._state.notes }} +- {{ . | wrapWith 98 "\n " -}} +{{ end }} + +{{ end -}} + +{{ if ._rox._state.warnings -}} +During installation, the following warnings were encountered: +{{ range ._rox._state.warnings }} +- WARNING: {{ . | wrapWith 98 "\n " -}} +{{ end }} + +{{ end -}} + +{{ if ._rox.env.openshift -}} +IMPORTANT: You have deployed into an OpenShift-enabled cluster. If you see that your pods + are not scheduling, run + + oc annotate namespace/{{ ._rox._namespace }} --overwrite openshift.io/node-selector="" +{{ end -}} + + +Thank you for using StackRox! diff --git a/4.3.8/secured-cluster-services/templates/_compatibility.tpl b/4.3.8/secured-cluster-services/templates/_compatibility.tpl new file mode 100644 index 0000000..c83ab2d --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_compatibility.tpl @@ -0,0 +1,51 @@ +{{ define "srox.applyCompatibilityTranslation" }} +{{ $ := index . 0 }} +{{ $values := index . 1 }} +{{ $translationRules := $.Files.Get "internal/compatibility-translation.yaml" | fromYaml }} +{{ include "srox._doApplyCompat" (list $values $.Template $values $translationRules list) }} +{{ end }} + +{{ define "srox._doApplyCompat" }} +{{ $values := index . 0 }} +{{ $template := index . 1 }} +{{ $valuesCtx := index . 2 }} +{{ $ruleCtx := index . 3 }} +{{ $ctxPath := index . 4 }} +{{ range $k, $v := $ruleCtx }} + {{ $oldVal := index $valuesCtx $k }} + {{ if not (kindIs "invalid" $oldVal) }} + {{ if kindIs "map" $v }} + {{ if kindIs "map" $oldVal }} + {{ include "srox._doApplyCompat" (list $values $template $oldVal $v (append $ctxPath $k)) }} + {{ if not $oldVal }} + {{ $_ := unset $valuesCtx $k }} + {{ end }} + {{ end }} + {{ else }} + {{ $_ := unset $valuesCtx $k }} + {{ if not (kindIs "invalid" $v) }} + {{ $tplCtx := dict "Template" $template "value" (toJson $oldVal) "rawValue" $oldVal }} + {{ $configFragment := tpl $v $tplCtx | fromYaml }} + {{ include "srox._mergeCompat" (list $values $configFragment (append $ctxPath $k) list) }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{ define "srox._mergeCompat" }} +{{ $values := index . 0 }} +{{ $newConfig := index . 1 }} +{{ $compatValuePath := index . 2 }} +{{ $path := index . 3 }} +{{ range $k, $v := $newConfig }} + {{ $currVal := index $values $k }} + {{ if kindIs "invalid" $currVal }} + {{ $_ := set $values $k $v }} + {{ else if and (kindIs "map" $v) (kindIs "map" $currVal) }} + {{ include "srox._mergeCompat" (list $currVal $v $compatValuePath (append $path $k)) }} + {{ else }} + {{ include "srox.fail" (printf "Conflict between legacy configuration values %s and explicitly set configuration value %s, please unset legacy value" (join "." $compatValuePath) (append $path $k | join ".")) }} + {{ end }} +{{ end }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_crypto.tpl b/4.3.8/secured-cluster-services/templates/_crypto.tpl new file mode 100644 index 0000000..1455288 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_crypto.tpl @@ -0,0 +1,239 @@ +{{/* + srox.configureCrypto $ $cryptoConfigPath $spec + + This helper function configures a private key or certificate (public cert + private key) + config entry, from an input config which is accessed via $cryptoConfigPath relative to + $._rox, which we'll refer to as $inputCfg. $inputCfg is expected to be a dict with at + least `key` and `generate` properties. If `generate` is null, it defaults to either `true` + on installations, and `false` on upgrades. `key` is an expandable string. + The result in either mode is written to a dict $outputCfg under $._rox accessed by the + $cryptoConfigPath, with a '_' prepended to the last path element. E.g., if + $cryptoConfigPath is "a.b.c", the input configuration will be read from $._rox.a.b.c, and + the output configuration will be stored in $._rox.a.b._c. + + Private key-only mode is selected if $spec.keyOnly contains a non-zero string, which specifies + the key algorithm to use. In this mode, if $inputCfg.key expands to a non-empty string, this + string will be copied to the `Key` property of $outputCfg. Otherwise, if $inputCfg.generate + is true (wrt. the above defaulting rules), a key with the algorithm prescribed by $spec.keyOnly + will be generated and stored in the `Key` property of $outputCfg. + + Certificate mode is the default. If $inputCfg.cert and $inputCfg.key expand to non-empty strings, + these strings will be copied to the `Cert` and `Key` properties of $outputCfg. Otherwise, if both + of them expand to empty strings (it is an error if only one of them expands to a non-empty + string), and $inputCfg.generate is true, a certificate and private key are generated with the + following options: + - If $inputCfg.ca is true, generate a CA certificate with common name $inputCfg.CN and a 5 year + validity duration. + - Otherwise, generate a leaf certificate with common name $inputCfg.CN and a 1 year validity + duration. The SANs for this certificate are derived from the base DNS name $inputCfg.dnsBase + according to "srox.computeSANs". + + Whenever certificates and/or private keys were generated, the $._rox._state.generated property + is updated to reflect the generated values, such that merging $._rox._state.generated in to + $.Values would have caused this template to simply use the generated values as-is. E.g., if + $cryptoConfigPath was "a.b.c" and $.Values.a.b.c.cert" and $.Values.a.b.c.key" were both empty, + $._rox._state.generated.a.b.c would be set to be a dict with `cert` and `key` properties of the + generated $outputCfg.Cert and $outputCfg.Key. + + If a certificate or private key was generated, $._rox._state.customCertGen is set to true. + */}} +{{- define "srox.configureCrypto" -}} +{{ $ := index . 0 }} +{{ $cryptoConfigPath := index . 1 }} +{{ $spec := index . 2 }} + +{{/* Resolve $cryptoConfigPath. */}} +{{ $cfg := $._rox }} +{{ $newGenerated := dict }} +{{ $genCfg := $newGenerated }} +{{ $cryptoConfigPathList := splitList "." $cryptoConfigPath }} +{{ range $pathElem := $cryptoConfigPathList }} + {{ $cfg = index $cfg $pathElem }} + {{ $newCfg := dict }} + {{ $_ := set $genCfg $pathElem $newCfg }} + {{ $genCfg = $newCfg }} +{{ end }} + +{{/* Make sure `cert` and `key` are expanded (this should already be the case, but better + safe than sorry. */}} +{{ $certExpandSpec := dict "cert" true "key" true }} +{{ include "srox.expandAll" (list $ $cfg $certExpandSpec $cryptoConfigPathList) }} + +{{ $certPEM := $cfg._cert }} +{{ $keyPEM := $cfg._key }} + +{{ $result := dict }} +{{ if $certPEM }} + {{ $result = dict "Cert" $certPEM "Key" (default "" $keyPEM) }} +{{ else if or $certPEM $keyPEM }} + {{ if and $keyPEM $spec.keyOnly }} + {{ $_ := set $result "Key" $keyPEM }} + {{ else }} + {{ include "srox.fail" (printf "Either none or both of %s.cert and %s.key must be specified" $cryptoConfigPath $cryptoConfigPath) }} + {{ end }} +{{ else }} + {{ $generate := $cfg.generate }} + {{ if kindIs "invalid" $generate }} + {{ $generate = $.Release.IsInstall }} + {{ end }} + {{ if $generate }} + {{ if $spec.ca }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"ca\" (genCA .cn 1825) }}" (dict "Template" $.Template "cn" $spec.CN "out" $out) }} + {{ $result = $out.ca }} + {{ else if $spec.keyOnly }} + {{ $key := tpl "{{ genPrivateKey .algo }}" (dict "Template" $.Template "algo" $spec.keyOnly) }} + {{ $_ := set $genCfg "key" $key }} + {{ $_ = set $result "Key" $key }} + {{ else }} + {{ if not $._rox._ca }} + {{ include "srox.fail" (printf "Tried to generate certificate for %s, but no CA certificate is available." $spec.CN) }} + {{ end }} + {{ $sans := dict }} + {{ include "srox.computeSANs" (list $ $sans $spec.dnsBase) }} + {{ $ca := $._rox._ca }} + {{ if kindIs "map" $ca }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"ca\" (buildCustomCert (b64enc .ca.Cert) (b64enc .ca.Key)) }}" (dict "Template" $.Template "ca" $ca "out" $out) }} + {{ $ca = $out.ca }} + {{ end }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"cert\" (genSignedCert .cn nil .sans 365 .ca) }}" (dict "Template" $.Template "cn" $spec.CN "sans" $sans.result "ca" $ca "out" $out) }} + {{ $result = $out.cert }} + {{ $_ := set $genCfg "cert" $result.Cert }} + {{ $_ = set $genCfg "key" $result.Key }} + {{ end }} + {{ $_ := set $genCfg "key" $result.Key }} + {{ if $result.Cert }} + {{ $_ = set $genCfg "cert" $result.Cert }} + {{ end }} + {{ $_ = set $._rox._state "customCertGen" true }} + {{ end }} +{{ end }} + +{{/* Store output configuration and generated properties */}} +{{ $newCfgRoot := dict }} +{{ $newCfg := $newCfgRoot }} +{{ range $pathElem := initial $cryptoConfigPathList }} + {{ $nextCfg := dict }} + {{ $_ := set $newCfg $pathElem $nextCfg }} + {{ $newCfg = $nextCfg }} +{{ end }} +{{ $_ := set $newCfg (last $cryptoConfigPathList | printf "_%s") $result }} +{{ $_ = include "srox.mergeInto" (list $._rox $newCfgRoot) }} +{{ $_ = include "srox.mergeInto" (list $._rox._state.generated $newGenerated) }} +{{ end }} + + +{{/* + srox.configurePassword $ $pwConfigPath [$htpasswdUser] + + This helper function reads a password configuration (YAML dict with `value` + and `generate` properties) referenced by $pwConfigPath relative to $._rox. It + ensures the dict with the same config path relative to $._rox and prepending an underscore + to the last path element is populated in the following way: + - If the `value` property of the input config is nonzero, set `value` in the result to the + expanded value. + - If the optional $htpasswdUser parameter is specified and the `htpasswd` property of the + input config is nonzero, set `htpasswd` in the result to the expanded value of that + property. + - If none of the above (non-mutually-exclusive) cases apply: + - If `generate` is true OR both `generate` is null and this is an installation, + not an upgrade, generate a random password with 32 alphanumeric characters. + - Otherwise, leave the result property empty. + - If the optional $htpasswdUser parameter was specified AND the `value` property in the + result property was set per the above rules AND the `htpasswd` property was not set, + populate the `htpasswd` property of the result by generating an htpasswd stanza with + the computed `value` as the password and $htpasswdUser as the username. + + The $._rox._state.generated property is adjusted accordingly. + */}} +{{- define "srox.configurePassword" -}} +{{ $ := index . 0 }} +{{ $pwConfigPath := index . 1 }} +{{ $htpasswdUser := "" }} +{{ if gt (len .) 2 }} + {{ $htpasswdUser = index . 2 }} +{{ end }} +{{ $cfg := $._rox }} +{{ $newGenerated := dict }} +{{ $genCfg := $newGenerated }} +{{ $pwConfigPathList := splitList "." $pwConfigPath }} +{{ range $pathElem := $pwConfigPathList }} + {{ $cfg = index $cfg $pathElem }} + {{ $newCfg := dict }} + {{ $_ := set $genCfg $pathElem $newCfg }} + {{ $genCfg = $newCfg }} +{{ end }} + +{{/* Make sure that `value` and `htpasswd` within $cfg are expanded (this should already be the + case but better safe than sorry). */}} +{{ $pwExpandSpec := dict "value" true "htpasswd" true }} +{{ include "srox.expandAll" (list $ $cfg $pwExpandSpec $pwConfigPathList) }} + +{{ $result := dict }} +{{ if and $htpasswdUser (not (kindIs "invalid" $cfg._htpasswd)) }} + {{ $htpasswd := $cfg._htpasswd }} + {{ $_ := set $result "htpasswd" $htpasswd }} +{{ end }} +{{ if not $result.htpasswd }} + {{ $pw := dict.nil }} + {{ if kindIs "invalid" $cfg._value }} + {{ $generate := $cfg.generate }} + {{ if kindIs "invalid" $generate }} + {{ $generate = $.Release.IsInstall }} + {{ end }} + {{ if $generate }} + {{ $pw = randAlphaNum 32 }} + {{ $_ := set $genCfg "value" $pw }} + {{ end }} + {{ else }} + {{ $pw = $cfg._value }} + {{ end }} + {{ if not (kindIs "invalid" $pw) }} + {{ $_ := set $result "value" $pw }} + {{ end }} + {{ if and $htpasswdUser $pw }} + {{ $htpasswd := tpl "{{ htpasswd .user .pw }}" (dict "Template" $.Template "user" $htpasswdUser "pw" $pw) }} + {{ $_ := set $result "htpasswd" $htpasswd }} + {{ end }} +{{ else if $cfg.value }} + {{ include "srox.fail" (printf "Both a htpasswd and a value are specified for %s, this is illegal. Remove the `value` property, or ensure that `htpasswd` is null." $pwConfigPath) }} +{{ end }} +{{ $newCfgRoot := dict }} +{{ $newCfg := $newCfgRoot }} +{{ range $pathElem := initial $pwConfigPathList }} + {{ $nextCfg := dict }} + {{ $_ := set $newCfg $pathElem $nextCfg }} + {{ $newCfg = $nextCfg }} +{{ end }} +{{ $_ := set $newCfg (last $pwConfigPathList | printf "_%s") $result }} +{{ $_ = include "srox.mergeInto" (list $._rox $newCfgRoot) }} +{{ $_ = include "srox.mergeInto" (list $._rox._state.generated $newGenerated) }} +{{ end }} + + +{{/* + srox.computeSANs $ $out $svcName + + Compute the applicable SANs for a service with name $svcName, deployed in namespace + $.Release.Namespace (= $releaseNS). + Generally, SANs following the pattern "$svcName.$releaseNS[.svc[.cluster.local]]" will be + generated. If $releaseNS is not "stackrox", another set of SANs with the same pattern, + but assuming $releaseNS = "stackrox", will be generated in addition. + The result is stored as a list in $out.result. + */}} +{{ define "srox.computeSANs" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ $svcName := index . 2 }} +{{ $releaseNS := $.Release.Namespace }} +{{ $sans := list }} +{{ range $ns := list $releaseNS "stackrox" | uniq | sortAlpha }} + {{ $baseDNS := printf "%s.%s" $svcName $ns }} + {{ range $suffix := tuple "" ".svc" ".svc.cluster.local" }} + {{ $sans = printf "%s%s" $baseDNS $suffix | append $sans }} + {{ end }} +{{ end }} +{{ $_ := set $out "result" $sans }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_defaults.tpl b/4.3.8/secured-cluster-services/templates/_defaults.tpl new file mode 100644 index 0000000..7f8629b --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_defaults.tpl @@ -0,0 +1,35 @@ +{{/* + srox.applyDefaults . + + Applies defaults defined in `internal/defaults`, in an order that depends on the filenames. + */}} +{{ define "srox.applyDefaults" }} +{{ $ := . }} +{{/* Apply defaults */}} +{{ range $defaultsFile, $defaultsTpl := $.Files.Glob "internal/defaults/*.yaml" }} + {{ $tplSects := regexSplit "(^|\n)---($|\n)" (toString $defaultsTpl) -1 }} + {{ $sectCounter := 0 }} + {{ range $tplSect := $tplSects }} + {{/* + tpl will merely stop creating output if an error is encountered during rendering (not during parsing), but we want + to be certain that we recognized invalid templates. Hence, add a marker line at the end, and verify that it + shows up in the output. + */}} + {{ $renderedSect := tpl (list $tplSect "{{ \"\\n#MARKER\\n\" }}" | join "") $ }} + {{ if not (hasSuffix "\n#MARKER\n" $renderedSect) }} + {{ include "srox.fail" (printf "Section %d in defaults file %s contains invalid templating" $sectCounter $defaultsFile) }} + {{ end }} + {{/* + fromYaml only returns an empty dict upon error, but we want to be certain that we recognized invalid YAML. + Hence, add a marker value. + */}} + {{ $sectDict := fromYaml (cat $renderedSect "\n__marker: true\n") }} + {{ if not (index $sectDict "__marker") }} + {{ include "srox.fail" (printf "Section %d in defaults file %s contains invalid YAML" $sectCounter $defaultsFile) }} + {{ end }} + {{ $_ := unset $sectDict "__marker" }} + {{ $_ = include "srox.mergeInto" (list $._rox $sectDict) }} + {{ $sectCounter = add $sectCounter 1 }} + {{ end }} +{{ end }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_dict.tpl b/4.3.8/secured-cluster-services/templates/_dict.tpl new file mode 100644 index 0000000..bf14a6d --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_dict.tpl @@ -0,0 +1,142 @@ +{{/* + srox.compactDict $target [$depth] + + Compacts a dict $target by removing entries with empty values. + By default, only the top-level dict $target itself is modified. If the optional $depth + parameter is specified and is non-zero, this determines the recursion depth over which the + compaction is applied to nested diocts as well. A $depth of -1 means to compact all nested + dicts, regardless of depth. + */}} +{{ define "srox.compactDict" }} +{{ $args := . }} +{{ if not (kindIs "slice" $args) }} + {{ $args = list $args 0 }} +{{ end }} +{{ $target := index $args 0 }} +{{ $depth := index $args 1 }} +{{ $zeroValKeys := list }} +{{ range $k, $v := $target }} + {{ if and (kindIs "map" $v) (ne $depth 0) }} + {{ include "srox.compactDict" (list $v (sub $depth 1)) }} + {{ end }} + {{ if not $v }} + {{ $zeroValKeys = append $zeroValKeys $k }} + {{ end }} +{{ end }} +{{ range $k := $zeroValKeys }} + {{ $_ := unset $target $k }} +{{ end }} +{{ end }} + +{{/* + srox.destructiveMergeOverwrite $out $dict1 $dict2... + + Recursively merges $dict1, $dict2 (in this order) into $out, similar to mergeOverwrite. + The eponymous difference is the fact that any explicit "null" entries in the source + dictionaries cause the respective entry to be deleted. + */}} +{{ define "srox.destructiveMergeOverwrite" }} +{{ $out := first . }} +{{ $toMergeList := rest . }} +{{ range $toMerge := $toMergeList }} + {{ range $k, $v := $toMerge }} + {{ if kindIs "invalid" $v }} + {{ $_ := unset $out $k }} + {{ else if kindIs "map" $v }} + {{ $outV := index $out $k }} + {{ if kindIs "invalid" $outV }} + {{ $_ := set $out $k (deepCopy $v) }} + {{ else if kindIs "map" $outV }} + {{ include "srox.destructiveMergeOverwrite" (list $outV $v) }} + {{ else }} + {{ fail (printf "when merging at key %s: incompatible kinds %s and %s" $k (kindOf $v) (kindOf $outV)) }} + {{ end }} + {{ else }} + {{ $_ := set $out $k $v }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox.stringifyDictValues $dict + + Recursively traverses $dict and converts every non-dict value to a string. + */}} +{{ define "srox.stringifyDictValues" }} +{{ $dict := . }} +{{ range $k, $v := $dict }} + {{ if kindIs "map" $v }} + {{ include "srox.stringifyDictValues" $v }} + {{ else }} + {{ $_ := set $dict $k (toString $v) }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox.safeDictLookup $dict $out $path + + Looks up $path in $dict, and stores the result (if any) in $out.result. + $path is a dot-separated list of nested field names. An empty $path causes + $dict to be stored in $out.result. + + Example: srox.safeDictLookup $dict $out "a.b.c" stores the value of $dict.a.b.c, if + it exists, in $out.result. Otherwise, it does nothing - in particular, it does + not fail, as accessing $dict.a.b.c unconditionally would if any of $dict, $dict.a, + or $dict.a.b was not a dict. + */}} +{{ define "srox.safeDictLookup" }} +{{ $dict := index . 0 }} +{{ $out := index . 1 }} +{{ $path := index . 2 }} +{{ $curr := $dict }} +{{ $pathList := splitList "." $path | compact }} +{{ range $pathElem := $pathList }} + {{ if kindIs "map" $curr }} + {{ $curr = index $curr $pathElem }} + {{ else if not (kindIs "invalid" $curr) }} + {{ $curr = dict.nil }} + {{ end }} +{{ end }} +{{ if not (kindIs "invalid" $curr) }} + {{ $_ := set $out "result" $curr }} +{{ end }} +{{ end }} + + + +{{/* + srox.mergeInto $tgt $src1..$srcN + + Recursively merges values from $src1, ..., $srcN into $tgt, giving preference to + values in $tgt. + + Unlike Sprig's merge, this does not overwrite falsy values when explicitly defined, + with the exception of `null` values (this also sets it apart from Sprig's mergeOverwrite). + + Whenever entire (nested) dicts are merged as-is from one of the sources into $tgt, a deep + copy of the respective nested dict is created. + + An empty string is always returned, hence this should be invoked in the form + $_ := include "srox.mergeInto" (list $tgt $src1 $src2) + */}} +{{ define "srox.mergeInto" }} +{{ $tgt := first . }} +{{ range $src := rest . }} + {{ range $k, $srcV := $src }} + {{ $tgtV := index $tgt $k }} + {{ if kindIs "map" $srcV }} + {{ if kindIs "invalid" $tgtV }} + {{ $_ := set $tgt $k (deepCopy $srcV) }} + {{ else if kindIs "map" $tgtV }} + {{ $_ := include "srox.mergeInto" (list $tgtV $srcV) }} + {{ else }} + {{ fail (printf "Incompatible kinds for key %s: %s vs %s" $k (kindOf $srcV) (kindOf $tgtV)) }} + {{ end }} + {{ else if and (not (kindIs "invalid" $srcV)) (kindIs "invalid" $tgtV) }} + {{ $_ := set $tgt $k $srcV }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_expand.tpl b/4.3.8/secured-cluster-services/templates/_expand.tpl new file mode 100644 index 0000000..ed1cb1f --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_expand.tpl @@ -0,0 +1,96 @@ +{{/* + srox.expandAll $ $target $expandable [$path] + + Expands values within $target that are flagged in $expandable, using $path + as the path from the configuration root to $target for error reporting purposes. + + If $target is nil, nothing happens. Otherwise, $target must be a dict. For every key + of $target that is also present in $expandable, the following action is performed: + - If the entry in $expandable is a dict, recursive invoke "srox.expandAll" on the + respective entries, with an adjusted $path. + - Otherwise, the entry in $expandable is assume to be of boolean value. If the value is + true, the corresponding entry's value in $target is expanded (see "srox._expandSingle" + below for a definition of expanding), and the result of the expansion is stored under + the key with a "_" prepended in $target. The original entry in $target is removed. This + ensures "srox.expandAll" is an idempotent operation). + */}} +{{ define "srox.expandAll" }} +{{ $args := . }} +{{ $ := index $args 0 }} +{{ $target := index $args 1 }} +{{ $expandable := index $args 2 }} +{{ $path := list }} +{{ if ge (len $args) 4 }} + {{ $path = index $args 3 }} + {{ if kindIs "string" $path }} + {{ $path = splitList "." $path | compact }} + {{ end }} +{{ end }} + +{{ if kindIs "map" $target }} + {{ range $k, $v := $expandable }} + {{ $childPath := append $path $k }} + {{ $targetV := index $target $k }} + {{ if kindIs "map" $v }} + {{ include "srox.expandAll" (list $ $targetV $v $childPath) }} + {{ else if $v }} + {{ if not (kindIs "invalid" $targetV) }} + {{ $expanded := include "srox._expandSingle" (list $ $targetV (join "." $childPath)) }} + {{ $_ := set $target (printf "_%s" $k) $expanded }} + {{ end }} + {{ $_ := unset $target $k }} + {{ end }} + {{ end }} +{{ else if not (kindIs "invalid" $target) }} + {{ include "srox.fail" (printf "Error expanding value at %s: expected map, got: %s" (join "." $path) (kindOf $target)) }} +{{ end }} +{{ end }} + +{{/* + srox.expand $ $spec + + Parses and expands a "specification string" in the following way: + - If $spec is a dictionary, return $spec rendered as a YAML. + - Otherwise, if $spec starts with a backslash character (`\`), return $spec minus the leading + backslash character. + - Otherwise, if $spec starts with an `@` character, strip off the first character and + treat the remainder of the string as a `|`-separated list of file names. Try to load + each referenced file, in order, via `stackrox.getFile`. The result is the first file + that could be successfully loaded. If no file could be loaded, expansion fails. + - Otherwise, return $spec as-is. + */}} +{{- define "srox._expandSingle" -}} + {{- $ := index . 0 -}} + {{- $spec := index . 1 -}} + {{- $context := index . 2 -}} + {{- $result := "" -}} + {{- if kindIs "string" $spec -}} + {{- if hasPrefix "\\" $spec -}} + {{- /* use \ as string-wide escape character */ -}} + {{- $result = trimPrefix "\\" $spec -}} + {{- else if hasPrefix "@" $spec -}} + {{- /* treat as file list (first found matches) */ -}} + {{- /* If the prefix is "@?" expansion will not fail if no files could be found, instead an empty string is returned. */ -}} + {{- $fileSpec := trimPrefix "@" $spec -}} + {{- $allowNotFound := false -}} + {{- if hasPrefix "?" $fileSpec -}} + {{- $allowNotFound = true -}} + {{- $fileSpec = trimPrefix "?" $fileSpec -}} + {{- end -}} + {{- $fileList := regexSplit "\\s*\\|\\s*" ($fileSpec | trim) -1 -}} + {{- $fileRes := dict -}} + {{- $_ := include "srox.loadFile" (list $ $fileRes $fileList) -}} + {{- if and (not $allowNotFound) (not $fileRes.found) -}} + {{- include "srox.fail" (printf "Expanding %s: file reference %q: none of the referenced files were found" $context $spec) -}} + {{- end -}} + {{- $result = default "" $fileRes.contents -}} + {{- else -}} + {{/* treat as raw string */}} + {{- $result = $spec -}} + {{- end -}} + {{- else if not (kindIs "invalid" $spec) -}} + {{- /* render non-string, non-nil values as YAML */ -}} + {{- $result = toYaml $spec -}} + {{- end -}} + {{- $result -}} +{{- end -}} diff --git a/4.3.8/secured-cluster-services/templates/_format.tpl b/4.3.8/secured-cluster-services/templates/_format.tpl new file mode 100644 index 0000000..745fe47 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_format.tpl @@ -0,0 +1,14 @@ +{{/* + srox.formatStorageSize $value + + Formats $value as a storage size. $value can be an integer or a string. + If no unit is specified (e.g., if $value is a string), a default unit of + Gigabytes ("Gi" suffix) is assumed. + */}} +{{- define "srox.formatStorageSize" -}} +{{- $val := toString . -}} +{{- if regexMatch "^[0-9]+$" $val -}} + {{- $val = printf "%sGi" $val -}} +{{- end -}} +{{- default "0" $val -}} +{{- end -}} diff --git a/4.3.8/secured-cluster-services/templates/_helpers.tpl b/4.3.8/secured-cluster-services/templates/_helpers.tpl new file mode 100644 index 0000000..e87f10f --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_helpers.tpl @@ -0,0 +1,68 @@ +{{/* + Misceallaneous helper templates. + */}} + + + + +{{/* + srox.loadFile $ $out $fileName-or-list + + This helper function reads a file. It differs from $.Files.Get in that it also takes + $._rox.meta.fileOverrides into account. Furthermore, it can receive a list of file names, + and will try these files in order. Finally, it indicates whether a file was found via the + $out.found property (as opposed to $.Files.Get, which cannot distinguish between a successful + read of an empty file, and this file not being found). + The file contents will be returned via $out.contents + */}} +{{ define "srox.loadFile" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ $fileNames := index . 2 }} +{{ if not (kindIs "slice" $fileNames) }} + {{ $fileNames = list $fileNames }} +{{ end }} +{{ $contents := index dict "" }} +{{ range $fileName := $fileNames }} + {{ if kindIs "invalid" $contents }} + {{ $contents = index $._rox.meta.fileOverrides $fileName }} + {{ end }} + {{ if kindIs "invalid" $contents }} + {{ range $path, $_ := $.Files.Glob $fileName }} + {{ if kindIs "invalid" $contents }} + {{ $contents = $.Files.Get $path }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ if not (kindIs "invalid" $contents) }} + {{ $_ := set $out "contents" $contents }} +{{ end }} +{{ $_ := set $out "found" (not (kindIs "invalid" $contents)) }} +{{ end }} + + +{{/* + srox.checkGenerated $ $cfgPath + + Checks if the value at configuration path $cfgPath (e.g., "central.adminPassword.value") was + generated. Evaluates to the string "true" if this is the case, and an empty string otherwise. + */}} +{{- define "srox.checkGenerated" -}} +{{- $ := index . 0 -}} +{{- $cfgPath := index . 1 -}} +{{- $genCfg := $._rox._state.generated -}} +{{- $exists := true -}} +{{- range $pathElem := splitList "." $cfgPath -}} + {{- if $exists -}} + {{- if hasKey $genCfg $pathElem -}} + {{- $genCfg = index $genCfg $pathElem -}} + {{- else -}} + {{- $exists = false -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $exists -}} +true +{{- end -}} +{{- end -}} diff --git a/4.3.8/secured-cluster-services/templates/_image-pull-secrets.tpl b/4.3.8/secured-cluster-services/templates/_image-pull-secrets.tpl new file mode 100644 index 0000000..9747e26 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_image-pull-secrets.tpl @@ -0,0 +1,85 @@ +{{/* + srox.configureImagePullSecrets $ $cfgName $imagePullSecrets $secretResourceName $defaultSecretNames $namespace + + Configures image pull secrets. + + This function enriches $imagePullSecrets based on the exposed configuration parameters to contain + a list of Kubernetes secret names as `_names` to be used as image pull secrets within the chart + templates. This list contains the following secrets: + + - Secrets referenced via $imagePullSecrets.useExisting. + - Image pull secrets associated with the default service account (if + $imagePullSecrets.useFromDefaultServiceAccount is true). + - $secretResourceName, if $imagePullSecrets.username is set. + - $defaultSecretNames. */}} + +{{ define "srox.configureImagePullSecrets" }} +{{ $ := index . 0 }} +{{ $cfgName := index . 1 }} +{{ $imagePullSecrets := index . 2 }} +{{ $secretResourceName := index . 3 }} +{{ $defaultSecretNames := index . 4 }} +{{ $namespace := index . 5 }} + +{{ $imagePullSecretNames := default list $imagePullSecrets.useExisting }} +{{ if not (kindIs "slice" $imagePullSecretNames) }} + {{ $imagePullSecretNames = regexSplit "\\s*[,;]\\s*" (trim $imagePullSecretNames) -1 }} +{{ end }} +{{ if $imagePullSecrets.useFromDefaultServiceAccount }} + {{ $defaultSA := dict }} + {{ include "srox.safeLookup" (list $ $defaultSA "v1" "ServiceAccount" $namespace "default") }} + {{ if $defaultSA.result }} + {{ range $ips := default list $defaultSA.result.imagePullSecrets }} + {{ if $ips.name }} + {{ $imagePullSecretNames = append $imagePullSecretNames $ips.name }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ $imagePullCreds := dict }} +{{ if $imagePullSecrets._username }} + {{ $imagePullCreds = dict "username" $imagePullSecrets._username "password" $imagePullSecrets._password }} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretResourceName }} +{{ else if $imagePullSecrets._password }} + {{ $msg := printf "Username missing in %q. Whenever an image pull password is specified, a username must be specified as well" $cfgName }} + {{ include "srox.fail" $msg }} +{{ end }} +{{ if and $.Release.IsInstall (not $imagePullSecretNames) (not $imagePullSecrets.allowNone) }} + {{ $msg := printf "You have not specified any image pull secrets, and no existing image pull secrets were automatically inferred. If your registry does not need image pull credentials, explicitly set the '%s.allowNone' option to 'true'" $cfgName }} + {{ include "srox.fail" $msg }} +{{ end }} + +{{ $imagePullSecretNames = concat (append $imagePullSecretNames $secretResourceName) $defaultSecretNames | uniq | sortAlpha }} +{{ $_ := set $imagePullSecrets "_names" $imagePullSecretNames }} +{{ $_ := set $imagePullSecrets "_creds" $imagePullCreds }} + +{{ end }} + +{{ define "srox.configureImagePullSecretsForDockerRegistry" }} +{{ $ := index . 0 }} +{{ $imagePullSecrets := index . 1 }} + +{{/* Setup Image Pull Secrets for Docker Registry. + Note: This must happen afterwards, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} +{{ if $imagePullSecrets._username }} + {{ $dockerAuths := dict }} + {{ range $image := keys $._rox._state.referencedImages }} + {{ $registry := splitList "/" $image | first }} + {{ if eq $registry "docker.io" }} + {{/* Special case docker.io */}} + {{ $registry = "https://index.docker.io/v1/" }} + {{ else }} + {{ $registry = printf "https://%s" $registry }} + {{ end }} + {{ $_ := set $dockerAuths $registry dict }} + {{ end }} + {{ $authToken := printf "%s:%s" $imagePullSecrets._username $imagePullSecrets._password | b64enc }} + {{ range $regSettings := values $dockerAuths }} + {{ $_ := set $regSettings "auth" $authToken }} + {{ end }} + + {{ $_ := set $imagePullSecrets "_dockerAuths" $dockerAuths }} +{{ end }} + +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_images.tpl b/4.3.8/secured-cluster-services/templates/_images.tpl new file mode 100644 index 0000000..dced29d --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_images.tpl @@ -0,0 +1,34 @@ +{{/* + srox.configureImage $ $imageCfg + + Configures settings for a single image by augmenting/completing an existing image configuration + stanza. + + If $imageCfg.fullRef is empty: + First, the image registry is determined by inspecting $imageCfg.registry and, if this is empty, + $._rox.image.registry, ultimately defaulting to `docker.io`. The full image ref is then + constructed from the registry, $imageCfg.name (must be non-empty), and $imageCfg.tag (may be + empty, in which case "latest" is assumed). The result is stored in $imageCfg.fullRef. + + Afterwards (irrespective of the previous check), $imageCfg.fullRef is modified by prepending + "docker.io/" if and only if it did not contain a remote yet (i.e., the part before the first "/" + did not contain a dot (DNS name) or colon (port)). + + Finally, the resulting $imageCfg.fullRef is stored as a dict entry with value `true` in the + $._rox._state.referencedImages dict. + */}} +{{ define "srox.configureImage" }} +{{ $ := index . 0 }} +{{ $imageCfg := index . 1 }} +{{ $imageRef := $imageCfg.fullRef }} +{{ if not $imageRef }} + {{ $imageRef = printf "%s/%s:%s" (coalesce $imageCfg.registry $._rox.image.registry "docker.io") $imageCfg.name (default "latest" $imageCfg.tag) }} +{{ end }} +{{ $imageComponents := splitList "/" $imageRef }} +{{ $firstComponent := index $imageComponents 0 }} +{{ if or (lt (len $imageComponents) 2) (and (not (contains ":" $firstComponent)) (not (contains "." $firstComponent))) }} + {{ $imageRef = printf "docker.io/%s" $imageRef }} +{{ end }} +{{ $_ := set $imageCfg "fullRef" $imageRef }} +{{ $_ = set $._rox._state.referencedImages $imageRef true }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_init.tpl b/4.3.8/secured-cluster-services/templates/_init.tpl new file mode 100644 index 0000000..fd50428 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_init.tpl @@ -0,0 +1,257 @@ +{{/* + srox.init $ + + Initialization template for the internal data structures. + This template is designed to be included in every template file, but will only be executed + once by leveraging state sharing between templates. + */}} +{{ define "srox.init" }} + +{{ $ := . }} + +{{/* + On first(!) instantiation, set up the $._rox structure, containing everything required by + the resource template files. + */}} +{{ if not $._rox }} + +{{/* + Calculate the fingerprint of the input config. + */}} +{{ $configFP := (.Values | toJson | sha256sum) }} + +{{/* + Initial Setup + */}} + +{{ $values := deepCopy $.Values }} +{{ include "srox.applyCompatibilityTranslation" (list $ $values) }} + +{{/* + $rox / ._rox is the dictionary in which _all_ data that is modified by the init logic + is stored. + We ensure that it has the required shape, and then right after merging the user-specified + $.Values, we apply some bootstrap defaults. + */}} +{{ $rox := deepCopy $values }} + + +{{ $configShape := $.Files.Get "internal/config-shape.yaml" | fromYaml }} + +{{/* Only merge scanner config shapes if feature flag is enabled and kubectl output is disabled */}} +{{ $configShapeScanner := $.Files.Get "internal/scanner-config-shape.yaml" | fromYaml }} + {{ $_ := include "srox.mergeInto" (list $rox $configShape $configShapeScanner) }} + + +{{ $_ = set $ "_rox" $rox }} + +{{/* Set the config fingerprint as computed or overridden via values. */}} +{{ $configFP = default $configFP $._rox.meta.configFingerprintOverride }} +{{ $_ = set $._rox "_configFP" $configFP }} + +{{/* Global state (accessed from sub-templates) */}} +{{ $state := dict "notes" list "warnings" list "referencedImages" dict "generated" dict }} +{{ $_ = set $._rox "_state" $state }} + +{{/* + API Server setup. The problem with `.Capabilities.APIVersions` is that Helm does not + allow setting overrides for those when using `helm template` or `--dry-run`. Thus, + if we rely on `.Capabilities.APIVersions` directly, we lose flexibility for our chart + in these settings. Therefore, we use custom fields such that a user in principle has + the option to inject via `--set`/`-f` everything we rely upon. + */}} +{{ $apiResources := list }} +{{ if not (kindIs "invalid" $._rox.meta.apiServer.overrideAPIResources) }} + {{ $apiResources = $._rox.meta.apiServer.overrideAPIResources }} +{{ else }} + {{ range $apiResource := $.Capabilities.APIVersions }} + {{ $apiResources = append $apiResources $apiResource }} + {{ end }} +{{ end }} +{{ if $._rox.meta.apiServer.extraAPIResources }} + {{ $apiResources = concat $apiResources $._rox.meta.apiServer.extraAPIResources }} +{{ end }} +{{ $apiServerVersion := coalesce $._rox.meta.apiServer.version $.Capabilities.KubeVersion.Version }} +{{ $apiServer := dict "apiResources" $apiResources "version" $apiServerVersion }} +{{ $_ = set $._rox "_apiServer" $apiServer }} + +{{/* + Environment setup +*/}} + +{{/* Detect openshift version */}} +{{ include "srox.autoSenseOpenshiftVersion" (list $) }} + +{{/* Openshift monitoring */}} +{{ if $._rox.enableOpenShiftMonitoring }} + {{ include "srox.warn" (list . "enableOpenShiftMonitoring option was replaced with monitoring.openshift.enabled") }} + {{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" true)) }} +{{ end }} +{{/* Default `monitoring.openshift.enabled = true` unless `env.openshift != 4`. */}} +{{ if kindIs "invalid" $._rox.monitoring.openshift.enabled }} +{{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" (eq $._rox.env.openshift 4))) }} +{{ end }} +{{ if and $._rox.monitoring.openshift.enabled (ne $._rox.env.openshift 4) }} + {{ include "srox.warn" (list . "'monitoring.openshift.enabled' is set to true, but the chart is not being deployed in an OpenShift 4 cluster. Proceeding with 'monitoring.openshift.enabled=false'.") }} + {{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" false)) }} +{{ end }} +{{/* Detect enablePodSecurityPolicies */}} +{{ include "srox.autoSensePodSecurityPolicies" (list $) }} + +{{ include "srox.applyDefaults" $ }} + +{{/* Expand applicable config values */}} +{{ $expandables := $.Files.Get "internal/expandables.yaml" | fromYaml }} +{{ include "srox.expandAll" (list $ $rox $expandables) }} + +{{/* + General validation of effective settings. + */}} + +{{ if not $.Release.IsUpgrade }} +{{ if ne $._rox._namespace "stackrox" }} + {{ if $._rox.allowNonstandardNamespace }} + {{ include "srox.note" (list $ (printf "You have chosen to deploy to namespace '%s'." $._rox._namespace)) }} + {{ else }} + {{ include "srox.fail" (printf "You have chosen to deploy to namespace '%s', not 'stackrox'. If this was accidental, please re-run helm with the '-n stackrox' option. Otherwise, if you need to deploy into this namespace, set the 'allowNonstandardNamespace' configuration value to true." $._rox._namespace) }} + {{ end }} +{{ end }} +{{ end }} + +{{/* If a cluster name should change the confirmNewClusterName value must match clusterName. */}} +{{ if and $._rox.confirmNewClusterName (ne $._rox.confirmNewClusterName $._rox.clusterName) }} + {{ include "srox.fail" (printf "Failed to change cluster name. Values for confirmNewClusterName '%s' did not match clusterName '%s'." $._rox.confirmNewClusterName $._rox.clusterName) }} +{{ end }} + + +{{ if not $.Release.IsUpgrade }} +{{ if ne $.Release.Name $.Chart.Name }} + {{ if $._rox.allowNonstandardReleaseName }} + {{ include "srox.warn" (list $ (printf "You have chosen a release name of '%s', not '%s'. Accompanying scripts and commands in documentation might require adjustments." $.Release.Name $.Chart.Name)) }} + {{ else }} + {{ include "srox.fail" (printf "You have chosen a release name of '%s', not '%s'. We strongly recommend using the standard release name. If you must use a different name, set the 'allowNonstandardReleaseName' configuration option to true." $.Release.Name $.Chart.Name) }} + {{ end }} +{{ end }} +{{ end }} + + + + + +{{ if and (not $._rox.auditLogs.disableCollection) (ne $._rox.env.openshift 4) }} + {{ include "srox.fail" "'auditLogs.disableCollection' is set to false, but the chart is not being deployed in OpenShift 4 mode. Set 'env.openshift' to '4' in order to enable OpenShift 4 features." }} +{{ end }} + + +{{ if and $._rox.admissionControl.dynamic.enforceOnCreates (not $._rox.admissionControl.listenOnCreates) }} + {{ include "srox.warn" (list $ "Incompatible settings: 'admissionControl.dynamic.enforceOnCreates' is set to true, while `admissionControl.listenOnCreates` is set to false. For the feature to be active, enable both settings by setting them to true.") }} +{{ end }} + +{{ if and $._rox.admissionControl.dynamic.enforceOnUpdates (not $._rox.admissionControl.listenOnUpdates) }} + {{ include "srox.warn" (list $ "Incompatible settings: 'admissionControl.dynamic.enforceOnUpdates' is set to true, while `admissionControl.listenOnUpdates` is set to false. For the feature to be active, enable both settings by setting them to true.") }} +{{ end }} + +{{ if and (eq $._rox.env.openshift 3) $._rox.admissionControl.listenOnEvents }} + {{ include "srox.fail" "'admissionControl.listenOnEvents' is set to true, but the chart is being deployed in OpenShift 3.x compatibility mode, which does not work with this feature. Set 'env.openshift' to '4' in order to enable OpenShift 4.x features." }} +{{ end }} +{{/* Initial image pull secret setup. */}} +{{ include "srox.mergeInto" (list $._rox.mainImagePullSecrets $._rox.imagePullSecrets) }} +{{ include "srox.configureImagePullSecrets" (list $ "mainImagePullSecrets" $._rox.mainImagePullSecrets "secured-cluster-services-main" (list "stackrox") $._rox._namespace) }} +{{ include "srox.mergeInto" (list $._rox.collectorImagePullSecrets $._rox.imagePullSecrets) }} +{{ include "srox.configureImagePullSecrets" (list $ "collectorImagePullSecrets" $._rox.collectorImagePullSecrets "secured-cluster-services-collector" (list "stackrox" "collector-stackrox") $._rox._namespace) }} + +{{/* Additional CAs. */}} +{{ $additionalCAList := list }} +{{ if kindIs "string" $._rox.additionalCAs }} + {{ if $._rox.additionalCAs }} + {{ $additionalCAList = append $additionalCAList (dict "name" "ca.crt" "contents" $._rox.additionalCAs) }} + {{ end }} +{{ else if kindIs "slice" $._rox.additionalCAs }} + {{ range $contents := $._rox.additionalCAs }} + {{ $additionalCAList = append $additionalCAList (dict "name" "ca.crt" "contents" $contents) }} + {{ end }} +{{ else if kindIs "map" $._rox.additionalCAs }} + {{ range $name := keys $._rox.additionalCAs | sortAlpha }} + {{ $additionalCAList = append $additionalCAList (dict "name" $name "contents" (get $._rox.additionalCAs $name)) }} + {{ end }} +{{ else if not (kindIs "invalid" $._rox.additionalCAs) }} + {{ include "srox.fail" (printf "Invalid kind %s for additionalCAs" (kindOf $._rox.additionalCAs)) }} +{{ end }} +{{ range $path, $contents := .Files.Glob "secrets/additional-cas/**" }} + {{ $name := trimPrefix "secrets/additional-cas/" $path }} + {{ $additionalCAList = append $additionalCAList (dict "name" $name "contents" (toString $contents)) }} +{{ end }} +{{ $additionalCAs := dict }} +{{ range $idx, $elem := $additionalCAList }} + {{ if not (kindIs "string" $elem.contents) }} + {{ include "srox.fail" (printf "Invalid non-string contents kind %s at index %d (%q) of additionalCAs" (kindOf $elem.contents) $idx $elem.name) }} + {{ end }} + {{/* In a k8s secret, no characters other than alphanumeric, '.', '_' and '-' are allowed. Also, for the + update-ca-certificates script to work, the file names must end in '.crt'. */}} + + {{ $normalizedName := printf "%02d-%s.crt" $idx (regexReplaceAll "[^[:alnum:]._-]" $elem.name "-" | trimSuffix ".crt") }} + {{ $_ := set $additionalCAs $normalizedName $elem.contents }} +{{ end }} +{{ $_ = set $._rox "_additionalCAs" $additionalCAs }} + +{{/* + Final validation (after merging in defaults). + */}} + +{{ if and ._rox.helmManaged (not ._rox.clusterName) }} + {{ include "srox.fail" "No cluster name specified. Set 'clusterName' to the desired cluster name." }} +{{ end }} + +{{/* Image settings */}} +{{ include "srox.configureImage" (list $ ._rox.image.main) }} +{{ include "srox.configureImage" (list $ ._rox.image.collector) }} +{{ include "srox.configureImage" (list $ ._rox.image.scanner) }} + +{{ include "srox.initGlobalPrefix" (list $) }} + +{{/* ManagedBy related settings */}} +{{/* The field `helmManaged` defaults to true, therefore `managedBy` will only be changed to `MANAGER_TYPE_MANUAL` here + in case it was explicitly set `helmManaged=false`. */}} +{{- if not ._rox.helmManaged }} + {{ $_ = set $._rox "managedBy" "MANAGER_TYPE_MANUAL" }} +{{- end }} + +{{/* + Local scanner setup. + */}} + +{{/* Disable scanner always in kubectl outputs */}} + + +{{ if eq ._rox.scanner.disable false }} + {{ $centralDeployment := dict }} + {{ include "srox.safeLookup" (list $ $centralDeployment "apps/v1" "Deployment" $.Release.Namespace "central") }} + {{ if $centralDeployment.result }} + {{ include "srox.note" (list $ "Detected central running in the same namespace. Not deploying scanner from this chart and configuring sensor to use existing scanner instance, if any.") }} + {{ $_ := set $._rox.sensor.localImageScanning "enabled" "true" }} + {{ $_ := set $._rox.scanner "disable" true }} + {{ end }} +{{ end }} + +{{ if eq ._rox.scanner.disable false }} + {{ if ne ._rox.scanner.mode "slim" }} + {{ include "srox.fail" (print "Only scanner slim mode is allowed in Secured Cluster. To solve this, set to slim mode: scanner.mode=slim.") }} + {{ end }} + + {{ $_ := set $._rox.sensor.localImageScanning "enabled" "true" }} + {{ $_ := set $._rox.scanner "slimImage" ._rox.image.scanner }} + {{ $_ := set $._rox.scanner "slimDBImage" ._rox.image.scannerDb }} + {{ include "srox.scannerInit" (list $ $._rox.scanner) }} + {{ include "srox.configureImagePullSecrets" (list $ "imagePullSecrets" $._rox.imagePullSecrets "secured-cluster-services-main" (list "stackrox" "stackrox-scanner") $.Release.Namespace) }} +{{ end }} + +{{/* + Post-processing steps. + */}} + +{{ include "srox.configureImagePullSecretsForDockerRegistry" (list $ ._rox.mainImagePullSecrets) }} +{{ include "srox.configureImagePullSecretsForDockerRegistry" (list $ ._rox.collectorImagePullSecrets) }} + +{{ end }} + +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_injected-ca-bundle.tpl b/4.3.8/secured-cluster-services/templates/_injected-ca-bundle.tpl new file mode 100644 index 0000000..f831139 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_injected-ca-bundle.tpl @@ -0,0 +1,29 @@ +{{/* + srox.injectedCABundleVolume + + Configures ConfigMap volume to use in a deployment. + */}} +{{- define "srox.injectedCABundleVolume" -}} +{{- if eq ._rox.env.openshift 4 }} +- name: trusted-ca-volume + configMap: + name: injected-cabundle-{{ .Release.Name }} + items: + - key: ca-bundle.crt + path: tls-ca-bundle.pem + optional: true +{{ end }} +{{ end }} + +{{/* + srox.injectedCABundleVolumeMount + + Mounts the srox.injectedCABundle volume to a container. + */}} +{{- define "srox.injectedCABundleVolumeMount" -}} +{{- if eq ._rox.env.openshift 4 }} +- name: trusted-ca-volume + mountPath: /etc/pki/injected-ca-trust/ + readOnly: true +{{ end }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_labels.tpl b/4.3.8/secured-cluster-services/templates/_labels.tpl new file mode 100644 index 0000000..52714db --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_labels.tpl @@ -0,0 +1,31 @@ +{{/* + srox._labels $labels $ $objType $objName $forPod + + Writes all applicable [pod] labels (including default labels) for $objType/$objName + into $labels. Pod labels are written iff $forPod is true. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.labels". + */}} +{{ define "srox._labels" }} +{{ $labels := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $forPod := index . 4 }} +{{ $_ := set $labels "app.kubernetes.io/name" "stackrox" }} +{{ $_ = set $labels "app.kubernetes.io/managed-by" $.Release.Service }} +{{ $_ = set $labels "helm.sh/chart" (printf "%s-%s" $.Chart.Name ($.Chart.Version | replace "+" "_")) }} +{{ $_ = set $labels "app.kubernetes.io/instance" $.Release.Name }} +{{ $_ = set $labels "app.kubernetes.io/version" $.Chart.AppVersion }} +{{ $_ = set $labels "app.kubernetes.io/part-of" "stackrox-secured-cluster-services" }} +{{ $component := regexReplaceAll "^.*/(admission-control|collector|sensor)[^/]*\\.yaml" $.Template.Name "${1}" }} +{{ if not (contains "/" $component) }} + {{ $_ = set $labels "app.kubernetes.io/component" $component }} +{{ end }} +{{ $metadataNames := list "labels" }} +{{ if $forPod }} + {{ $metadataNames = append $metadataNames "podLabels" }} +{{ end }} +{{ include "srox._customizeMetadata" (list $ $labels $objType $objName $metadataNames) }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_lookup.tpl b/4.3.8/secured-cluster-services/templates/_lookup.tpl new file mode 100644 index 0000000..17f6306 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_lookup.tpl @@ -0,0 +1,40 @@ +{{/* + srox.safeLookup $ $out $apiVersion $kind $ns $name + + This function does nothing if $.meta.useLookup is false; otherwise, it will + perform a `lookup $apiVersion $kind $ns $name` operation and store the result in + $out.result. + + Additionally, if a lookup was attempted, $out.reliable will contain a bool indicating + whether the result of lookup can be relied upon. This is determined to be the case if + the default service account in the release namespace can be found. + */}} +{{ define "srox.safeLookup" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ if $._rox.meta.useLookup }} + {{ if kindIs "invalid" $._rox._state.lookupWorks }} + {{ $testOut := dict }} + {{ include "srox._doLookup" (list $ $testOut "v1" "ServiceAccount" $._rox._namespace "default") }} + {{ $_ := set $._rox._state "lookupWorks" ($testOut.result | not | not) }} + {{ end }} + {{ include "srox._doLookup" . }} + {{ $_ := set $out "reliable" $._rox._state.lookupWorks }} +{{ end }} +{{ end }} + + +{{/* + srox._doLookup $ $out $apiVersion $kind $ns $name + + Calls "lookup" with arguments $apiVersion $kind $ns $name, and stores the result + in $out.result. + + This function exists to prevent a parse error if the lookup function isn't defined. It does + so by deferring the execution of lookup to a template string instantiated via `tpl`. + */}} +{{ define "srox._doLookup" }} +{{ $ := index . 0 }} +{{ $tplArgs := dict "Template" $.Template "out" (index . 1) "apiVersion" (index . 2) "kind" (index . 3) "ns" (index . 4) "name" (index . 5) }} +{{ $_ := tpl "{{ $_ := set .out \"result\" (lookup .apiVersion .kind .ns .name) }}" $tplArgs }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_metadata.tpl b/4.3.8/secured-cluster-services/templates/_metadata.tpl new file mode 100644 index 0000000..3ed131f --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_metadata.tpl @@ -0,0 +1,194 @@ +{{/* + srox.labels $ $objType $objName + + Format labels for $objType/$objName as YAML. + */}} +{{- define "srox.labels" -}} +{{- $labels := dict -}} +{{- $_ := include "srox._labels" (append (prepend . $labels) false) -}} +{{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.podLabels $ $objType $objName + + Format pod labels for $objType/$objName as YAML. + */}} +{{- define "srox.podLabels" -}} +{{- $labels := dict -}} +{{- $_ := include "srox._labels" (append (prepend . $labels) true) -}} +{{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.annotations $ $objType $objName + + Format annotations for $objType/$objName as YAML. + */}} +{{- define "srox.annotations" -}} +{{- $annotations := dict -}} +{{- $_ := include "srox._annotations" (append (prepend . $annotations) false) -}} +{{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.podAnnotations $ $objType $objName + + Format pod annotations for $objType/$objName as YAML. + */}} +{{- define "srox.podAnnotations" -}} +{{- $annotations := dict -}} +{{- $_ := include "srox._annotations" (append (prepend . $annotations) true) -}} +{{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.envVars $ $objType $objName $containerName + + Format environment variables for container $containerName in + $objType/$objName as YAML. + */}} +{{- define "srox.envVars" -}} +{{- $envVars := dict -}} +{{- $_ := include "srox._envVars" (prepend . $envVars) -}} +{{- range $k := keys $envVars | sortAlpha -}} +{{- $v := index $envVars $k }} +- name: {{ quote $k }} +{{- if kindIs "map" $v }} + {{- toYaml $v | nindent 2 }} +{{- else }} + value: {{ quote $v }} +{{- end }} +{{ end -}} +{{- end -}} + +{{/* + srox._annotations $annotations $ $objType $objName $forPod + + Writes all applicable [pod] annotations (including default annotations) for + $objType/$objName into $annotations. Pod labels are written iff $forPod is true. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.annotations". + */}} +{{ define "srox._annotations" }} +{{ $annotations := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $forPod := index . 4 }} +{{ $_ := set $annotations "meta.helm.sh/release-namespace" $.Release.Namespace }} +{{ $_ = set $annotations "meta.helm.sh/release-name" $.Release.Name }} +{{ $_ = set $annotations "owner" "stackrox" }} +{{ $_ = set $annotations "email" "support@stackrox.com" }} +{{ $metadataNames := list "annotations" }} +{{ if $forPod }} + {{ $metadataNames = append $metadataNames "podAnnotations" }} +{{ end }} +{{ include "srox._customizeMetadata" (list $ $annotations $objType $objName $metadataNames) }} +{{ end }} + +{{/* + srox._envVars $envVars $ $objType $objName $containerName + + Writes all applicable environment variables for $objType/$objName + into $envVars. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.envVars". + */}} +{{ define "srox._envVars" }} +{{ $envVars := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $containerName := index . 4 }} +{{ $metadataNames := list "envVars" }} +{{ include "srox._customizeMetadata" (list $ $envVars $objType $objName $metadataNames) }} +{{ if $containerName }} + {{ $containerKey := printf "/%s" $containerName }} + {{ $envVarsForContainer := index $envVars $containerKey }} + {{ if $envVarsForContainer }} + {{ include "srox.destructiveMergeOverwrite" (list $envVars $envVarsForContainer) }} + {{ end }} +{{ end }} + +{{/* Remove all entries starting with / */}} +{{ range $key, $_ := $envVars }} + {{ if hasPrefix "/" $key }} + {{ $_ := unset $envVars $key }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox._customizeMetadata $ $metadata $objType $objName $metadataNames + + Writes custom key/value metadata to $metadata by consulting all sub-dicts with names in + $metadataNames under the applicable custom metadata locations (._rox.customize, + ._rox.customize.other.$objType/*, ._rox.customize.other.$objType/$objName, and + ._rox.customizer.$objName [workloads only]). Dictionaries are consulted in this order, with + values from dictionaries consulted later overwriting values from dictionaries consulted + earlier. + */}} +{{ define "srox._customizeMetadata" }} +{{ $ := index . 0 }} +{{ $metadata := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $metadataNames := index . 4 }} + +{{ $overrideDictPaths := list "" (printf "other.%s/*" $objType) (printf "other.%s/%s" $objType $objName) }} +{{ if has $objType (list "deployment" "daemonset") }} + {{ $overrideDictPaths = append $overrideDictPaths $objName }} +{{ end }} + +{{ range $dictPath := $overrideDictPaths }} + {{ $customizeDict := $._rox.customize }} + {{ if $dictPath }} + {{ $resolvedOut := dict }} + {{ include "srox.safeDictLookup" (list $._rox.customize $resolvedOut $dictPath) }} + {{ $customizeDict = $resolvedOut.result }} + {{ end }} + {{ if $customizeDict }} + {{ range $metadataName := $metadataNames }} + {{ $customMetadata := index $customizeDict $metadataName }} + {{ include "srox.destructiveMergeOverwrite" (list $metadata $customMetadata) }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{/* Add namespace specific prefixes for global resources to avoid resource name clashes for multi-namespace deployments. */}} +{{- define "srox.globalResourceName" -}} +{{- $ := index . 0 -}} +{{- $name := index . 1 -}} + +{{- if eq $.Release.Namespace "stackrox" -}} + {{- /* Standard namespace, use resource name as is. */ -}} + {{- $name -}} +{{- else -}} + {{- /* Add global prefix to resource name. */ -}} + {{- printf "%s-%s" $._rox.globalPrefix (trimPrefix "stackrox-" $name) -}} +{{- end -}} +{{- end -}} + +{{/* + srox.initGlobalPrefix $ + + Initializes prefix for global resources. + */}} +{{- define "srox.initGlobalPrefix" -}} +{{- $ := index . 0 -}} +{{ if kindIs "invalid" $._rox.globalPrefix }} + {{ if eq $.Release.Namespace "stackrox" }} + {{ $_ := set $._rox "globalPrefix" "stackrox" }} + {{ else }} + {{ $_ := set $._rox "globalPrefix" (printf "stackrox-%s" (trimPrefix "stackrox-" $.Release.Namespace)) }} + {{ end }} +{{ end }} + +{{ if ne $._rox.globalPrefix "stackrox" }} + {{ include "srox.note" (list $ (printf "Global Kubernetes resources are prefixed with '%s'." $._rox.globalPrefix)) }} +{{- end -}} +{{- end -}} diff --git a/4.3.8/secured-cluster-services/templates/_openshift.tpl b/4.3.8/secured-cluster-services/templates/_openshift.tpl new file mode 100644 index 0000000..85201cb --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_openshift.tpl @@ -0,0 +1,47 @@ +{{/* + srox.autoSenseOpenshiftVersion $ + + This function detects the OpenShift version automatically based on the cluster the Helm chart is installed onto. + It writes the result to ._rox.env.openshift as an integer. + Possible results are: + - 3 (OpenShift 3) + - 4 (OpenShift 4) + - 0 (Non-Openshift cluster) + + If "true" is passed for $._rox.env.openshift the OpenShift version is detected based on the Kubernetes cluster version. + If the Kubernetes version is not available (i.e. when using Helm template) auto-sensing falls back on OpenShift 3 to be + backward compatible. + */}} + +{{ define "srox.autoSenseOpenshiftVersion" }} + +{{ $ := index . 0 }} +{{ $env := $._rox.env }} + +{{/* Infer OpenShift, if needed */}} +{{ if kindIs "invalid" $env.openshift }} + {{ $_ := set $env "openshift" (has "apps.openshift.io/v1" $._rox._apiServer.apiResources) }} +{{ end }} + +{{/* Infer openshift version */}} +{{ if and $env.openshift (kindIs "bool" $env.openshift) }} + {{/* Parse and add KubeVersion as semver from built-in resources. This is necessary to compare valid integer numbers. */}} + {{ $kubeVersion := semver $.Capabilities.KubeVersion.Version }} + + {{/* Default to OpenShift 3 if no openshift resources are available, i.e. in helm template commands */}} + {{ if not (has "apps.openshift.io/v1" $._rox._apiServer.apiResources) }} + {{ $_ := set $._rox.env "openshift" 3 }} + {{ else if gt $kubeVersion.Minor 11 }} + {{ $_ := set $env "openshift" 4 }} + {{ else }} + {{ $_ := set $env "openshift" 3 }} + {{ end }} + {{ include "srox.note" (list $ (printf "Based on API server properties, we have inferred that you are deploying into an OpenShift %d.x cluster. Set the `env.openshift` property explicitly to 3 or 4 to override the auto-sensed value." $env.openshift)) }} +{{ end }} +{{ if not (kindIs "bool" $env.openshift) }} + {{ $_ := set $env "openshift" (int $env.openshift) }} +{{ else if not $env.openshift }} + {{ $_ := set $env "openshift" 0 }} +{{ end }} + +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_psp.tpl b/4.3.8/secured-cluster-services/templates/_psp.tpl new file mode 100644 index 0000000..bffb2a0 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_psp.tpl @@ -0,0 +1,19 @@ +{{/* + srox.autoSensePodSecurityPolicies $ + */}} + +{{ define "srox.autoSensePodSecurityPolicies" }} + +{{ $ := index . 0 }} +{{ $system := $._rox.system }} + +{{ if kindIs "invalid" $system.enablePodSecurityPolicies }} + {{ $_ := set $system "enablePodSecurityPolicies" (has "policy/v1beta1" $._rox._apiServer.apiResources) }} + {{ if $system.enablePodSecurityPolicies }} + {{ include "srox.note" (list $ (printf "PodSecurityPolicies are enabled, since your environment supports them according to API server properties.")) }} + {{ else }} + {{ include "srox.note" (list $ (printf "PodSecurityPolicies are disabled, since your environment does not support them according to API server properties.")) }} + {{ end }} +{{ end }} + +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_reporting.tpl b/4.3.8/secured-cluster-services/templates/_reporting.tpl new file mode 100644 index 0000000..621e284 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_reporting.tpl @@ -0,0 +1,34 @@ +{{/* + srox.fail $message + + Print a nicely-formatted fatal error message and exit. + */}} +{{ define "srox.fail" }} +{{ printf "\n\nFATAL ERROR:\n%s" . | wrap 100 | fail }} +{{ end }} + +{{/* + srox.warn $ $message + + Add $message to the list of encountered warnings. + */}} +{{ define "srox.warn" }} +{{ $ := index . 0 }} +{{ $msg := index . 1 }} +{{ $warnings := $._rox._state.warnings }} +{{ $warnings = append $warnings $msg }} +{{ $_ := set $._rox._state "warnings" $warnings }} +{{ end }} + +{{/* + srox.note $ $message + + Add $message to the list notes that will be shown to the user after installation/upgrade. + */}} +{{ define "srox.note" }} +{{ $ := index . 0 }} +{{ $msg := index . 1 }} +{{ $notes := $._rox._state.notes }} +{{ $notes = append $notes $msg }} +{{ $_ := set $._rox._state "notes" $notes }} +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/_scanner_init.tpl b/4.3.8/secured-cluster-services/templates/_scanner_init.tpl new file mode 100644 index 0000000..75fbe95 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/_scanner_init.tpl @@ -0,0 +1,40 @@ +{{/* + srox.scannerInit . $scannerConfig + + Initializes the scanner configuration. The scanner chart has two modes "full" and + "slim". + The "full" mode is used for stand-alone deployments, mostly along with StackRox's Central service. In this + mode, the image contains vulnerability data and the Helm chart can create its own certificates. + + The "slim" mode is used to deploy Scanner with a smaller image and does not generate TLS certificates, + typically deployed within a Secured Cluster to scan images stored in a registry only accessible to the current cluster. + The scanner chart defaults to "full" mode if no mode was provided. + + $scannerConfig contains all values which are configured by the user. The structure can be viewed in the according + config-shape. See internal/scanner-config-shape.yaml. + */}} + +{{ define "srox.scannerInit" }} + +{{ $ := index . 0 }} +{{ $scannerCfg := index . 1 }} + +{{ if or (eq $scannerCfg.mode "") (eq $scannerCfg.mode "full") }} + {{ include "srox.configureImage" (list $ $scannerCfg.image) }} + {{ include "srox.configureImage" (list $ $scannerCfg.dbImage) }} + + {{ $scannerCertSpec := dict "CN" "SCANNER_SERVICE: Scanner" "dnsBase" "scanner" }} + {{ include "srox.configureCrypto" (list $ "scanner.serviceTLS" $scannerCertSpec) }} + + {{ $scannerDBCertSpec := dict "CN" "SCANNER_DB_SERVICE: Scanner DB" "dnsBase" "scanner-db" }} + {{ include "srox.configureCrypto" (list $ "scanner.dbServiceTLS" $scannerDBCertSpec) }} +{{ else if eq $scannerCfg.mode "slim" }} + {{ include "srox.configureImage" (list $ $scannerCfg.slimImage) }} + {{ include "srox.configureImage" (list $ $scannerCfg.slimDBImage) }} +{{ else }} + {{ include "srox.fail" (printf "Unknown scanner mode %s" $scannerCfg.mode) }} +{{ end }} + +{{ include "srox.configurePassword" (list $ "scanner.dbPassword") }} + +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/additional-ca-sensor.yaml b/4.3.8/secured-cluster-services/templates/additional-ca-sensor.yaml new file mode 100644 index 0000000..aa1801c --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/additional-ca-sensor.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} + +{{- if ._rox._additionalCAs }} +apiVersion: v1 +kind: Secret +metadata: + name: additional-ca-sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "additional-ca-sensor") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "additional-ca-sensor") | nindent 4 }} +type: Opaque +stringData: + {{- range $name, $cert := ._rox._additionalCAs }} + {{ $name | quote }}: | + {{- $cert | nindent 4 }} + {{- end }} +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/admission-controller-netpol.yaml b/4.3.8/secured-cluster-services/templates/admission-controller-netpol.yaml new file mode 100644 index 0000000..1ab0341 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/admission-controller-netpol.yaml @@ -0,0 +1,46 @@ +{{- include "srox.init" . -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: admission-control-no-ingress + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "admission-control-no-ingress") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "admission-control-no-ingress") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: admission-control + ingress: + - ports: + - protocol: TCP + port: 8443 + policyTypes: + - Ingress + +{{- if ._rox.admissionControl.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: admission-control-monitoring + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "admission-control-monitoring") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "admission-control-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: admission-control + policyTypes: + - Ingress +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/admission-controller-pod-security.yaml b/4.3.8/secured-cluster-services/templates/admission-controller-pod-security.yaml new file mode 100644 index 0000000..d4011f4 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/admission-controller-pod-security.yaml @@ -0,0 +1,76 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.system.enablePodSecurityPolicies }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: stackrox-admission-control + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-admission-control") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-admission-control") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'secret' + - 'downwardAPI' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox-admission-control-psp + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-admission-control-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-admission-control-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - stackrox-admission-control + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-admission-control-psp + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-admission-control-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-admission-control-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: stackrox-admission-control-psp +subjects: + - kind: ServiceAccount + name: admission-control + namespace: {{ ._rox._namespace }} +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/admission-controller-rbac.yaml b/4.3.8/secured-cluster-services/templates/admission-controller-rbac.yaml new file mode 100644 index 0000000..1e4e11e --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/admission-controller-rbac.yaml @@ -0,0 +1,50 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: admission-control + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "admission-control") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "admission-control") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.mainImagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: watch-config + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "role" "watch-config") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "role" "watch-config") | nindent 4 }} +rules: + - apiGroups: [''] + resources: ['configmaps'] + verbs: ['get', 'list', 'watch'] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: admission-control-watch-config + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "admission-control-watch-config") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "admission-control-watch-config") | nindent 4 }} +subjects: + - kind: ServiceAccount + name: admission-control + namespace: {{ ._rox._namespace }} +roleRef: + kind: Role + name: watch-config + apiGroup: rbac.authorization.k8s.io diff --git a/4.3.8/secured-cluster-services/templates/admission-controller-scc.yaml b/4.3.8/secured-cluster-services/templates/admission-controller-scc.yaml new file mode 100644 index 0000000..e6bb807 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/admission-controller-scc.yaml @@ -0,0 +1,46 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} + +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: stackrox-admission-control + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-admission-control") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-admission-control") | nindent 4 }} + kubernetes.io/description: stackrox-admission-control is the security constraint for the admission controller +users: + - system:serviceaccount:{{ ._rox._namespace }}:admission-control +priority: 0 +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +supplementalGroups: + type: RunAsAny +fsGroup: + type: RunAsAny +groups: [] +readOnlyRootFilesystem: true +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +allowedCapabilities: [] +defaultAddCapabilities: [] +requiredDropCapabilities: [] +volumes: + - configMap + - downwardAPI + - emptyDir + - secret + +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/admission-controller-secret.yaml b/4.3.8/secured-cluster-services/templates/admission-controller-secret.yaml new file mode 100644 index 0000000..3abcb9a --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/admission-controller-secret.yaml @@ -0,0 +1,30 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.createSecrets (and (kindIs "invalid" ._rox.createSecrets) (or ._rox.admissionControl.serviceTLS._cert ._rox.admissionControl.serviceTLS._key)) }} + +{{/* Admission control TLS secret isn't required, so do not fail here. */}} +{{- if and ._rox.ca._cert ._rox.admissionControl.serviceTLS._cert ._rox.admissionControl.serviceTLS._key }} + +apiVersion: v1 +kind: Secret +metadata: + name: admission-control-tls + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "admission-control-tls") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + {{- include "srox.annotations" (list . "secret" "admission-control-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox.ca._cert | nindent 4 }} + admission-control-cert.pem: | + {{- ._rox.admissionControl.serviceTLS._cert | nindent 4 }} + admission-control-key.pem: | + {{- ._rox.admissionControl.serviceTLS._key | nindent 4 }} + +{{- end }} +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/admission-controller.yaml b/4.3.8/secured-cluster-services/templates/admission-controller.yaml new file mode 100644 index 0000000..778076d --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/admission-controller.yaml @@ -0,0 +1,246 @@ +{{- include "srox.init" . -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: admission-control + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "deployment" "admission-control") | nindent 4 }} + app: admission-control + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "deployment" "admission-control") | nindent 4 }} +spec: + replicas: {{ ._rox.admissionControl.replicas }} + minReadySeconds: 0 + selector: + matchLabels: + app: admission-control + template: + metadata: + namespace: {{ ._rox._namespace }} + labels: + app: admission-control + {{- include "srox.podLabels" (list . "deployment" "admission-control") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8443" + {{- include "srox.podAnnotations" (list . "deployment" "admission-control") | nindent 8 }} + spec: + # Attempt to schedule these on master nodes + {{- if ._rox.admissionControl.tolerations }} + tolerations: + {{- toYaml ._rox.admissionControl.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.admissionControl.affinity | nindent 8 }} + {{- if ._rox.admissionControl._nodeSelector }} + nodeSelector: + {{- ._rox.admissionControl._nodeSelector | nindent 8 }} + {{- end}} + {{- if not ._rox.env.openshift }} + securityContext: + runAsUser: 4000 + fsGroup: 4000 + {{- end }} + serviceAccountName: admission-control + containers: + - image: {{ quote ._rox.image.main.fullRef }} + imagePullPolicy: {{ ._rox.admissionControl.imagePullPolicy }} + name: admission-control + readinessProbe: + httpGet: + scheme: HTTPS + path: /ready + port: 8443 + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 1 + ports: + - containerPort: 8443 + name: webhook + command: + - admission-control + resources: + {{- ._rox.admissionControl._resources | nindent 12 }} + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: ROX_SENSOR_ENDPOINT + value: {{ ._rox.sensor.endpoint }} + {{- include "srox.envVars" (list . "deployment" "admission-controller" "admission-controller") | nindent 10 }} + volumeMounts: + - name: config + mountPath: /run/config/stackrox.io/admission-control/config/ + readOnly: true + - name: config-store + mountPath: /var/lib/stackrox/admission-control/ + - name: ca + mountPath: /run/secrets/stackrox.io/ca/ + readOnly: true + - name: certs + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: ssl + mountPath: /etc/ssl + - name: pki + mountPath: /etc/pki/ca-trust/ + - name: additional-cas + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + {{- include "srox.injectedCABundleVolumeMount" . | nindent 12 }} + volumes: + - name: certs + secret: + secretName: admission-control-tls + optional: true + items: + - key: admission-control-cert.pem + path: cert.pem + - key: admission-control-key.pem + path: key.pem + - key: ca.pem + path: ca.pem + - name: ca + secret: + secretName: service-ca + optional: true + - name: config + configMap: + name: admission-control + optional: true + - name: config-store + emptyDir: {} + - name: ssl + emptyDir: {} + - name: pki + emptyDir: {} + - name: additional-cas + secret: + secretName: additional-ca-sensor + optional: true + {{- include "srox.injectedCABundleVolume" . | nindent 8 }} +--- + +apiVersion: v1 +kind: Service +metadata: + name: admission-control + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "service" "admission-control") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "service" "admission-control") | nindent 4 }} +spec: + ports: + - name: https + port: 443 + targetPort: webhook + protocol: TCP + selector: + app: admission-control + type: ClusterIP + sessionAffinity: None +--- +{{- if ne ._rox.env.openshift 3 }} +apiVersion: admissionregistration.k8s.io/v1 +{{- else }} +apiVersion: admissionregistration.k8s.io/v1beta1 +{{- end }} +kind: ValidatingWebhookConfiguration +metadata: + name: stackrox + labels: + {{- include "srox.labels" (list . "validatingwebhookconfiguration" "stackrox") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "validatingwebhookconfiguration" "stackrox") | nindent 4 }} +{{- if not (or ._rox.admissionControl.listenOnEvents ._rox.admissionControl.listenOnCreates ._rox.admissionControl.listenOnUpdates) }} +webhooks: [] +{{- else }} +webhooks: + {{- if or ._rox.admissionControl.listenOnCreates ._rox.admissionControl.listenOnUpdates }} + - name: policyeval.stackrox.io + {{- if ne ._rox.env.openshift 3 }} + sideEffects: NoneOnDryRun + admissionReviewVersions: [ "v1", "v1beta1" ] + timeoutSeconds: {{ add 2 ._rox.admissionControl.dynamic.timeout }} + {{- end }} + rules: + - apiGroups: + - '*' + apiVersions: + - '*' + operations: + {{- if ._rox.admissionControl.listenOnCreates }} + - CREATE + {{- end }} + {{- if ._rox.admissionControl.listenOnUpdates }} + - UPDATE + {{- end }} + resources: + - pods + - deployments + - replicasets + - replicationcontrollers + - statefulsets + - daemonsets + - cronjobs + - jobs + {{- if ._rox.env.openshift }} + - deploymentconfigs + {{- end }} + namespaceSelector: + matchExpressions: + - key: namespace.metadata.stackrox.io/name + operator: NotIn + values: + - stackrox + - kube-system + - kube-public + - istio-system + failurePolicy: Ignore + clientConfig: + caBundle: {{ required "The 'ca.cert' config option MUST be set to StackRox's Service CA certificate in order for the admission controller to be usable" ._rox.ca._cert | b64enc }} + service: + namespace: {{ ._rox._namespace }} + name: admission-control + path: /validate + {{- end}} + {{- if ._rox.admissionControl.listenOnEvents }} + - name: k8sevents.stackrox.io + {{- if ne ._rox.env.openshift 3 }} + sideEffects: NoneOnDryRun + admissionReviewVersions: [ "v1", "v1beta1" ] + timeoutSeconds: {{ add 2 ._rox.admissionControl.dynamic.timeout }} + {{- end }} + rules: + - apiGroups: + - '*' + apiVersions: + - '*' + operations: + - CONNECT + resources: + - pods + - pods/exec + - pods/portforward + failurePolicy: Ignore + clientConfig: + caBundle: {{ required "The 'ca.cert' config option MUST be set to StackRox's Service CA certificate in order for the admission controller to be usable" ._rox.ca._cert | b64enc }} + service: + namespace: {{ ._rox._namespace }} + name: admission-control + path: /events + {{- end }} +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/cluster-config.yaml b/4.3.8/secured-cluster-services/templates/cluster-config.yaml new file mode 100644 index 0000000..20c81f6 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/cluster-config.yaml @@ -0,0 +1,14 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: Secret +metadata: + name: helm-cluster-config + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "helm-cluster-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "helm-cluster-config") | nindent 4 }} +stringData: + config.yaml: | + {{- tpl (.Files.Get "internal/cluster-config.yaml.tpl") . | nindent 4 }} diff --git a/4.3.8/secured-cluster-services/templates/collector-netpol.yaml b/4.3.8/secured-cluster-services/templates/collector-netpol.yaml new file mode 100644 index 0000000..3cf9214 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/collector-netpol.yaml @@ -0,0 +1,44 @@ +{{- include "srox.init" . -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: collector-no-ingress + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "collector-no-ingress") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "collector-no-ingress") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: collector + policyTypes: + - Ingress + +{{ if ._rox.collector.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: collector-monitoring + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "collector-monitoring") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "collector-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: collector + policyTypes: + - Ingress +{{ end }} diff --git a/4.3.8/secured-cluster-services/templates/collector-pod-security.yaml b/4.3.8/secured-cluster-services/templates/collector-pod-security.yaml new file mode 100644 index 0000000..d11ef4b --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/collector-pod-security.yaml @@ -0,0 +1,72 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox-collector-psp + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-collector-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-collector-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - stackrox-collector + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-collector-psp + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-collector-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-collector-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: stackrox-collector-psp +subjects: + - kind: ServiceAccount + name: collector + namespace: {{ ._rox._namespace }} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: stackrox-collector + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-collector") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-collector") | nindent 4 }} +spec: + privileged: true + allowPrivilegeEscalation: true + allowedCapabilities: + - '*' + volumes: + - '*' + allowedHostPaths: + - pathPrefix: / + readOnly: true + hostNetwork: false + hostIPC: false + hostPID: true + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/collector-rbac.yaml b/4.3.8/secured-cluster-services/templates/collector-rbac.yaml new file mode 100644 index 0000000..5d4ffd9 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/collector-rbac.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: collector + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "collector") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "collector") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := concat ._rox.collectorImagePullSecrets._names ._rox.mainImagePullSecrets._names | uniq }} +- name: {{ quote $secretName }} +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/collector-scc.yaml b/4.3.8/secured-cluster-services/templates/collector-scc.yaml new file mode 100644 index 0000000..48d47dc --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/collector-scc.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} + +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: stackrox-collector + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-collector") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-collector") | nindent 4 }} + kubernetes.io/description: This SCC is based on privileged, hostaccess, and hostmount-anyuid +users: + - system:serviceaccount:{{ ._rox._namespace }}:collector +allowHostDirVolumePlugin: true +allowPrivilegedContainer: true +fsGroup: + type: RunAsAny +groups: [] +priority: 0 +readOnlyRootFilesystem: true +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +supplementalGroups: + type: RunAsAny +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: true +allowedCapabilities: [] +defaultAddCapabilities: [] +requiredDropCapabilities: [] +volumes: + - configMap + - downwardAPI + - emptyDir + - hostPath + - secret + +{{- else if eq ._rox.env.openshift 4 }} + +{{- if false }} +# "fake" document separator to aid GVK extraction heuristic +--- +{{- end }} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-privileged-scc + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-privileged-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-privileged-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - privileged + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: collector-use-scc + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "collector-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "collector-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-privileged-scc +subjects: +- kind: ServiceAccount + name: collector + namespace: {{ ._rox._namespace }} + +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/collector-secret.yaml b/4.3.8/secured-cluster-services/templates/collector-secret.yaml new file mode 100644 index 0000000..6b07ea2 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/collector-secret.yaml @@ -0,0 +1,30 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.createSecrets (and (kindIs "invalid" ._rox.createSecrets) (or ._rox.collector.serviceTLS._cert ._rox.collector.serviceTLS._key)) }} + +{{- if not (and ._rox.ca._cert ._rox.collector.serviceTLS._cert ._rox.collector.serviceTLS._key) }} + {{ include "srox.fail" "Requested secret creation, but not all of CA certificate, collector certificate, collector private key are available. Set the 'createSecrets' config option to false if you do not want secrets to be created." }} +{{- end }} + +apiVersion: v1 +kind: Secret +metadata: + labels: + {{- include "srox.labels" (list . "secret" "collector-tls") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + {{- include "srox.annotations" (list . "secret" "collector-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" + name: collector-tls + namespace: {{ ._rox._namespace }} +type: Opaque +stringData: + ca.pem: | + {{- ._rox.ca._cert | nindent 4 }} + collector-cert.pem: | + {{- ._rox.collector.serviceTLS._cert | nindent 4 }} + collector-key.pem: | + {{- ._rox.collector.serviceTLS._key | nindent 4 }} + +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/collector.yaml b/4.3.8/secured-cluster-services/templates/collector.yaml new file mode 100644 index 0000000..756c367 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/collector.yaml @@ -0,0 +1,218 @@ +{{- include "srox.init" . -}} + +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + {{- include "srox.labels" (list . "daemonset" "collector") | nindent 4 }} + service: collector + app: collector + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "daemonset" "collector") | nindent 4 }} + name: collector + namespace: {{ ._rox._namespace }} +spec: + selector: + matchLabels: + service: collector + template: + metadata: + namespace: {{ ._rox._namespace }} + labels: + service: collector + app: collector + {{- include "srox.podLabels" (list . "daemonset" "collector") | nindent 8 }} + annotations: + {{- include "srox.podAnnotations" (list . "daemonset" "collector") | nindent 8 }} + spec: + {{- if not ._rox.collector.disableTaintTolerations }} + tolerations: + {{- toYaml ._rox.collector.tolerations | nindent 6 }} + {{- end }} + {{- if ._rox.collector._nodeSelector }} + nodeSelector: + {{- ._rox.collector._nodeSelector | nindent 8 }} + {{- end}} + serviceAccountName: collector + containers: + {{- if ne ._rox.collector.collectionMethod "NO_COLLECTION"}} + - name: collector + image: {{ quote ._rox.image.collector.fullRef }} + imagePullPolicy: {{ ._rox.collector.imagePullPolicy }} + {{- if ._rox.collector.exposeMonitoring }} + ports: + - containerPort: 9090 + name: monitoring + {{- end }} + env: + - name: COLLECTOR_CONFIG + value: '{"tlsConfig":{"caCertPath":"/var/run/secrets/stackrox.io/certs/ca.pem","clientCertPath":"/var/run/secrets/stackrox.io/certs/cert.pem","clientKeyPath":"/var/run/secrets/stackrox.io/certs/key.pem"}}' + - name: COLLECTION_METHOD + value: {{ ._rox.collector.collectionMethod }} + - name: GRPC_SERVER + value: {{ ._rox.sensor.endpoint }} + - name: SNI_HOSTNAME + value: "sensor.stackrox.svc" + {{- include "srox.envVars" (list . "daemonset" "collector" "collector") | nindent 8 }} + resources: + {{- ._rox.collector._resources | nindent 10 }} + securityContext: + capabilities: + drop: + - NET_RAW + privileged: true + readOnlyRootFilesystem: true + volumeMounts: + - mountPath: /host/proc + name: proc-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /module + name: tmpfs-module + - mountPath: /host/etc + name: etc-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /host/usr/lib + name: usr-lib-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /host/sys + name: sys-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /host/dev + name: dev-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /run/secrets/stackrox.io/certs/ + name: certs + readOnly: true + {{- end }} + - command: + - stackrox/compliance + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: ROX_CALL_NODE_INVENTORY_ENABLED + value: {{ if eq ._rox.env.openshift 4 }}"true"{{ else }}"false"{{ end }} + - name: ROX_METRICS_PORT + {{- if ._rox.collector.exposeMonitoring }} + value: ":9091" + {{- else}} + value: "disabled" + {{- end }} + - name: ROX_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: ROX_ADVERTISED_ENDPOINT + value: {{ quote ._rox.sensor.endpoint }} + - name: ROX_NODE_SCANNING_ENDPOINT + value: {{ quote ._rox.collector.nodescanningEndpoint }} + {{- include "srox.envVars" (list . "daemonset" "collector" "compliance") | nindent 8 }} + image: {{ quote ._rox.image.main.fullRef }} + imagePullPolicy: {{ ._rox.collector.complianceImagePullPolicy }} + name: compliance + {{- if ._rox.collector.exposeMonitoring }} + ports: + - containerPort: 9091 + name: monitoring + {{- end }} + resources: + {{- ._rox.collector._complianceResources | nindent 10 }} + securityContext: + runAsUser: 0 + readOnlyRootFilesystem: true + {{ if not ._rox.collector.disableSELinuxOptions }} + seLinuxOptions: + type: {{ ._rox.collector.seLinuxOptionsType | default "container_runtime_t" | quote }} + {{ end }} + volumeMounts: + - mountPath: /etc/ssl/ + name: etc-ssl + - mountPath: /etc/pki/ca-trust/ + name: etc-pki-volume + - mountPath: /host + name: host-root-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /run/secrets/stackrox.io/certs/ + name: certs + readOnly: true + {{- if eq ._rox.env.openshift 4 }} + - name: node-inventory + image: {{ quote ._rox.image.scanner.fullRef }} + imagePullPolicy: IfNotPresent + command: ["/scanner", "--nodeinventory", "--config=", ""] + ports: + - containerPort: 8444 + name: grpc + resources: + {{- ._rox.collector._nodeScanningResources | nindent 10 }} + env: + - name: ROX_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + {{- include "srox.envVars" (list . "daemonset" "collector" "node-inventory") | nindent 8 }} + volumeMounts: + - mountPath: /host + name: host-root-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /tmp/ + name: tmp-volume + - mountPath: /cache + name: cache-volume + {{- end }} + volumes: + - hostPath: + path: /proc + name: proc-ro + - emptyDir: + medium: Memory + name: tmpfs-module + - hostPath: + path: /etc + name: etc-ro + - hostPath: + path: /usr/lib + name: usr-lib-ro + - hostPath: + path: /sys/ + name: sys-ro + - hostPath: + path: /dev + name: dev-ro + - name: certs + secret: + secretName: collector-tls + items: + - key: collector-cert.pem + path: cert.pem + - key: collector-key.pem + path: key.pem + - key: ca.pem + path: ca.pem + - hostPath: + path: / + name: host-root-ro + - name: etc-ssl + emptyDir: {} + - name: etc-pki-volume + emptyDir: {} + - name: tmp-volume + emptyDir: {} + - name: cache-volume + emptyDir: + sizeLimit: 200Mi diff --git a/4.3.8/secured-cluster-services/templates/openshift-monitoring.yaml b/4.3.8/secured-cluster-services/templates/openshift-monitoring.yaml new file mode 100644 index 0000000..5b0aa89 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/openshift-monitoring.yaml @@ -0,0 +1,121 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.monitoring.openshift.enabled -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: secured-cluster-prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "secured-cluster-prometheus-k8s") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "role" "secured-cluster-prometheus-k8s") | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: secured-cluster-prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "secured-cluster-prometheus-k8s") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "secured-cluster-prometheus-k8s") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: secured-cluster-prometheus-k8s +subjects: +- kind: ServiceAccount + name: prometheus-k8s + namespace: openshift-monitoring + +--- + +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: "sensor-monitor-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "servicemonitor" (print "sensor-monitor-" .Release.Namespace)) | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "servicemonitor" (print "sensor-monitor-" .Release.Namespace)) | nindent 4 }} +spec: + endpoints: + - interval: 30s + path: metrics + port: monitoring-tls + scheme: https + tlsConfig: + caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt + certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt + keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key + serverName: "sensor.{{ .Release.Namespace }}.svc" + selector: + matchLabels: + app.kubernetes.io/component: sensor + namespaceSelector: + matchNames: + - "{{ .Release.Namespace }}" + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "rhacs-sensor-auth-reader-{{ .Release.Namespace }}" + namespace: kube-system + labels: + {{- include "srox.labels" (list . "rolebinding" (print "rhacs-sensor-auth-reader-" .Release.Namespace)) | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" (print "rhacs-sensor-auth-reader-" .Release.Namespace)) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: sensor + namespace: "{{ .Release.Namespace }}" + +--- + +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: "sensor-telemeter-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "prometheusrule" (print "sensor-telemeter-" .Release.Namespace )) | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "prometheusrule" (print "sensor-telemeter-" .Release.Namespace )) | nindent 4 }} +spec: + groups: + - name: rhacs.telemeter + rules: + - expr: | + max by (build, central_id, hosting, install_method, sensor_id, sensor_version) ( + rox_sensor_info{branding="RHACS"} + ) + record: rhacs:telemetry:rox_sensor_info + +{{- end -}} diff --git a/4.3.8/secured-cluster-services/templates/sensor-netpol.yaml b/4.3.8/secured-cluster-services/templates/sensor-netpol.yaml new file mode 100644 index 0000000..50d0d6e --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/sensor-netpol.yaml @@ -0,0 +1,88 @@ +{{- include "srox.init" . -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "sensor") | nindent 4 }} +spec: + ingress: + - from: + - podSelector: + matchLabels: + app: collector + - podSelector: + matchLabels: + service: collector + - podSelector: + matchLabels: + app: admission-control +{{ if ._rox.sensor.localImageScanning.enabled }} + - podSelector: + matchLabels: + app: scanner +{{ end }} + ports: + - port: 8443 + protocol: TCP + - ports: + - port: 9443 + protocol: TCP + podSelector: + matchLabels: + app: sensor + policyTypes: + - Ingress + +{{ if ._rox.sensor.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: sensor-monitoring + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "sensor-monitoring") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "sensor-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: sensor + policyTypes: + - Ingress +{{ end }} + +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: sensor-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "sensor-monitoring-tls") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "sensor-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: sensor + policyTypes: + - Ingress +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/sensor-pod-security.yaml b/4.3.8/secured-cluster-services/templates/sensor-pod-security.yaml new file mode 100644 index 0000000..e44a807 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/sensor-pod-security.yaml @@ -0,0 +1,82 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox-sensor-psp + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-sensor-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-sensor-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - stackrox-sensor + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-sensor-psp + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-sensor-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-sensor-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: stackrox-sensor-psp +subjects: + - kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} + - kind: ServiceAccount + name: sensor-upgrader + namespace: {{ ._rox._namespace }} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: stackrox-sensor + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-sensor") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + - 'hostPath' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/sensor-rbac.yaml b/4.3.8/secured-cluster-services/templates/sensor-rbac.yaml new file mode 100644 index 0000000..fb061be --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/sensor-rbac.yaml @@ -0,0 +1,293 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "sensor") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.mainImagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} + +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:view-cluster + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:view-cluster") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:view-cluster") | nindent 4 }} +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - get + - watch + - list +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:monitor-cluster + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:monitor-cluster") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:monitor-cluster") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:view-cluster + apiGroup: rbac.authorization.k8s.io +--- +# Role edit has all verbs but 'use' to disallow using any SCCs (resources: *). +# The permission to 'use' SCCs should be defined at finer granularity in other roles. +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: edit + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "role" "edit") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "role" "edit") | nindent 4 }} +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - create + - get + - list + - watch + - update + - patch + - delete + - deletecollection +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: manage-namespace + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "manage-namespace") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "manage-namespace") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: Role + name: edit + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:edit-workloads + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:edit-workloads") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:edit-workloads") | nindent 4 }} +rules: +- resources: + - cronjobs + - jobs + - daemonsets + - deployments + - deployments/scale + - deploymentconfigs + - pods + - replicasets + - replicationcontrollers + - services + - statefulsets + apiGroups: + - '*' + verbs: + - update + - patch + - delete +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:enforce-policies + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:enforce-policies") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:enforce-policies") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:edit-workloads + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:network-policies + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:network-policies") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:network-policies") | nindent 4 }} +rules: +- resources: + - 'networkpolicies' + apiGroups: + - networking.k8s.io + - extensions + verbs: + - get + - watch + - list + - create + - update + - patch + - delete +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:network-policies-binding + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:network-policies-binding") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:network-policies-binding") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:network-policies + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:update-namespaces + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:update-namespaces") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:update-namespaces") | nindent 4 }} +rules: +- resources: + - namespaces + apiGroups: [""] + verbs: + - update +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:update-namespaces-binding + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:update-namespaces-binding") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:update-namespaces-binding") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:update-namespaces + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:create-events + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:create-events") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:create-events") | nindent 4 }} +rules: +- resources: + - events + apiGroups: [""] + verbs: + - create + - patch + - list +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:create-events-binding + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:create-events-binding") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:create-events-binding") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:create-events + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:review-tokens + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:review-tokens") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:review-tokens") | nindent 4 }} +rules: +- resources: + - tokenreviews + apiGroups: ["authentication.k8s.io"] + verbs: + - create +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:review-tokens-binding + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:review-tokens-binding") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:review-tokens-binding") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:review-tokens + apiGroup: rbac.authorization.k8s.io diff --git a/4.3.8/secured-cluster-services/templates/sensor-scc.yaml b/4.3.8/secured-cluster-services/templates/sensor-scc.yaml new file mode 100644 index 0000000..b24a8fc --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/sensor-scc.yaml @@ -0,0 +1,47 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} + +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: stackrox-sensor + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-sensor") | nindent 4 }} + kubernetes.io/description: stackrox-sensor is the security constraint for the sensor +users: + - system:serviceaccount:{{ ._rox._namespace }}:sensor + - system:serviceaccount:{{ ._rox._namespace }}:sensor-upgrader +priority: 0 +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +supplementalGroups: + type: RunAsAny +fsGroup: + type: RunAsAny +groups: [] +readOnlyRootFilesystem: true +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: true +allowPrivilegedContainer: false +allowedCapabilities: [] +defaultAddCapabilities: [] +requiredDropCapabilities: [] +volumes: + - configMap + - downwardAPI + - emptyDir + - secret + +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/sensor-secret.yaml b/4.3.8/secured-cluster-services/templates/sensor-secret.yaml new file mode 100644 index 0000000..848e1f2 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/sensor-secret.yaml @@ -0,0 +1,30 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.createSecrets (and (kindIs "invalid" ._rox.createSecrets) (or ._rox.sensor.serviceTLS._cert ._rox.sensor.serviceTLS._key)) }} + +{{- if not (and ._rox.ca._cert ._rox.sensor.serviceTLS._cert ._rox.sensor.serviceTLS._key) }} + {{ include "srox.fail" "Requested secret creation, but not all of CA certificate, sensor certificate, sensor private key are available. Set the 'createSecrets' config option to false if you do not want secrets to be created." }} +{{- end }} + +apiVersion: v1 +kind: Secret +metadata: + name: sensor-tls + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "sensor-tls") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + {{- include "srox.annotations" (list . "secret" "sensor-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox.ca._cert | nindent 4 }} + sensor-cert.pem: | + {{- ._rox.sensor.serviceTLS._cert | nindent 4 }} + sensor-key.pem: | + {{- ._rox.sensor.serviceTLS._key | nindent 4 }} + +{{- end }} diff --git a/4.3.8/secured-cluster-services/templates/sensor.yaml b/4.3.8/secured-cluster-services/templates/sensor.yaml new file mode 100644 index 0000000..2534f42 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/sensor.yaml @@ -0,0 +1,280 @@ +{{- include "srox.init" . -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "deployment" "sensor") | nindent 4 }} + app: sensor + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "deployment" "sensor") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: sensor + strategy: + type: Recreate + template: + metadata: + labels: + app: sensor + {{- include "srox.podLabels" (list . "deployment" "sensor") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8443,9443" + {{- include "srox.podAnnotations" (list . "deployment" "sensor") | nindent 8 }} + spec: + {{- if ._rox.sensor._nodeSelector }} + nodeSelector: + {{- ._rox.sensor._nodeSelector | nindent 8 }} + {{- end}} + {{- if ._rox.sensor.tolerations }} + tolerations: + {{- toYaml ._rox.sensor.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.sensor.affinity | nindent 8 }} + {{- if not ._rox.env.openshift }} + securityContext: + runAsUser: 4000 + fsGroup: 4000 + {{- end }} + serviceAccountName: sensor + containers: + - image: {{ quote ._rox.image.main.fullRef }} + imagePullPolicy: {{ ._rox.sensor.imagePullPolicy }} + name: sensor + readinessProbe: + httpGet: + scheme: HTTPS + path: /ready + port: 9443 + ports: + - containerPort: 8443 + name: api + - containerPort: 9443 + name: webhook + {{- if ._rox.sensor.exposeMonitoring }} + - containerPort: 9090 + name: monitoring + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - containerPort: 9091 + name: monitoring-tls + {{- end }} + command: + - kubernetes-sensor + resources: + {{- ._rox.sensor._resources | nindent 10 }} + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ROX_CENTRAL_ENDPOINT + value: {{ ._rox.centralEndpoint }} + - name: ROX_ADVERTISED_ENDPOINT + value: {{ ._rox.sensor.endpoint }} + {{- if ._rox.env.openshift }} + - name: ROX_OPENSHIFT_API + value: "true" + {{- end }} + {{- if ._rox.sensor.localImageScanning.enabled }} + - name: ROX_SCANNER_GRPC_ENDPOINT + value: {{ printf "scanner.%s.svc:8443" .Release.Namespace }} + - name: ROX_LOCAL_IMAGE_SCANNING_ENABLED + value: "true" + {{- end }} + - name: ROX_HELM_CLUSTER_CONFIG_FP + value: {{ quote ._rox._configFP }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + {{- end }} + {{- include "srox.envVars" (list . "deployment" "sensor" "sensor") | nindent 8 }} + volumeMounts: + - name: varlog + mountPath: /var/log/stackrox/ + - name: sensor-etc-ssl-volume + mountPath: /etc/ssl/ + - name: sensor-etc-pki-volume + mountPath: /etc/pki/ca-trust/ + - name: certs + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: cache + mountPath: /var/cache/stackrox + - name: helm-cluster-config + mountPath: /run/secrets/stackrox.io/helm-cluster-config/ + readOnly: true + - name: helm-effective-cluster-name + mountPath: /run/secrets/stackrox.io/helm-effective-cluster-name/ + readOnly: true + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + volumes: + - name: certs + secret: + secretName: sensor-tls + items: + - key: sensor-cert.pem + path: cert.pem + - key: sensor-key.pem + path: key.pem + - key: ca.pem + path: ca.pem + - name: sensor-etc-ssl-volume + emptyDir: {} + - name: sensor-etc-pki-volume + emptyDir: {} + - name: additional-ca-volume + secret: + secretName: additional-ca-sensor + optional: true + - name: varlog + emptyDir: {} + - name: cache + emptyDir: {} + - name: helm-cluster-config + secret: + secretName: helm-cluster-config + optional: true + - name: helm-effective-cluster-name + secret: + secretName: helm-effective-cluster-name + optional: true + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: sensor-monitoring-tls + optional: true + {{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + name: sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "service" "sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "service" "sensor") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: sensor-monitoring-tls + {{- end }} +spec: + ports: + - name: https + port: 443 + targetPort: api + protocol: TCP + {{- if ._rox.sensor.exposeMonitoring }} + - name: monitoring + port: 9090 + targetPort: monitoring + protocol: TCP + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + port: 9091 + targetPort: monitoring-tls + protocol: TCP + {{- end }} + selector: + app: sensor + type: ClusterIP + sessionAffinity: None +--- + +{{- if ._rox.env.istio }} +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: sensor-internal-no-istio-mtls + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "sensor-internal-no-istio-mtls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "destinationrule" "sensor-internal-no-istio-mtls") | nindent 4 }} + stackrox.io/description: "Disable Istio mTLS for port 443, since StackRox services use built-in mTLS." +spec: + host: sensor.stackrox.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 443 + tls: + mode: DISABLE +--- +{{- end }} + +apiVersion: v1 +kind: Service +metadata: + name: sensor-webhook + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "service" "sensor-webhook") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "service" "sensor-webhook") | nindent 4 }} +spec: + ports: + - name: https + port: 443 + targetPort: webhook + protocol: TCP + selector: + app: sensor + type: ClusterIP + sessionAffinity: None +{{- if or .Release.IsInstall (eq ._rox.confirmNewClusterName ._rox.clusterName) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: helm-effective-cluster-name + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "helm-effective-cluster-name") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" + {{- include "srox.annotations" (list . "secret" "helm-effective-cluster-name") | nindent 4 }} +stringData: + cluster-name: | + {{- ._rox.clusterName | nindent 4 }} +{{- end}} diff --git a/4.3.8/secured-cluster-services/templates/service-ca.yaml b/4.3.8/secured-cluster-services/templates/service-ca.yaml new file mode 100644 index 0000000..3f3b5fd --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/service-ca.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: Secret +metadata: + name: service-ca + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "service-ca") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + {{- include "srox.annotations" (list . "secret" "service-ca") | nindent 4 }} +type: Opaque +stringData: + ca.pem: | + {{- required "A CA certificate must be specified" ._rox.ca._cert | nindent 4 }} diff --git a/4.3.8/secured-cluster-services/templates/upgrader-serviceaccount.yaml b/4.3.8/secured-cluster-services/templates/upgrader-serviceaccount.yaml new file mode 100644 index 0000000..af12eb1 --- /dev/null +++ b/4.3.8/secured-cluster-services/templates/upgrader-serviceaccount.yaml @@ -0,0 +1,36 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.createUpgraderServiceAccount }} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sensor-upgrader + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "sensor-upgrader") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "sensor-upgrader") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.mainImagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:upgrade-sensors + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:upgrade-sensors") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:upgrade-sensors") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor-upgrader + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io + +{{- end }} diff --git a/4.3.8/secured-cluster-services/values-private.yaml.example b/4.3.8/secured-cluster-services/values-private.yaml.example new file mode 100644 index 0000000..ecdec21 --- /dev/null +++ b/4.3.8/secured-cluster-services/values-private.yaml.example @@ -0,0 +1,19 @@ +# # BEGIN CONFIGURATION VALUES SECTION +# +# # Image pull credentials. If you do not specify these, you need to specify one of +# # the following: +# # - `imagePullSecrets.allowNone=true`: in case your registry allows pulling images without +# # credentials. +# # - `imagePullSecrets.useExisting="secret1;secret2;..."`: in case you have pre-existing image +# # pull secrets with the given name already created in the target namespace. +# # - `imagePullSecrets.useFromDefaultServiceAccount=true`: in case the default service account +# # in the target namespace is configured with sufficiently scoped image pull secrets. +# # +# # Since the above settings do not expose any confidential data, they can safely be added +# # to the values-public.yaml configuration file or provided on the command line. +# +# # If you do not know if any of the above applies to your situation, your best course of +# # action is probably to enter your image pull credentials here. +# imagePullSecrets: +# username: +# password: diff --git a/4.3.8/secured-cluster-services/values-public.yaml.example b/4.3.8/secured-cluster-services/values-public.yaml.example new file mode 100644 index 0000000..5bb9dc4 --- /dev/null +++ b/4.3.8/secured-cluster-services/values-public.yaml.example @@ -0,0 +1,465 @@ +# StackRox Kubernetes Security Platform - Secured Cluster Services Chart +# PUBLIC configuration file. +# +# This file contains general configuration values relevant for the deployment of the +# StackRox Kubernetes Platform Secured Cluster Services components, which do not contain +# or reference sensitive data. This file can and should be stored in a source code +# management system and should be referenced on each `helm upgrade`. +# +# Most of the values in this file are optional, and you only should need to make modifications +# if the default deployment configuration is not sufficient for you for whatever reason. +# The most notable exceptios are +# +# - `clusterName`, +# - `centralEndpoint` and +# - `imagePullSecrets`. +# +# # BEGIN CONFIGURATION VALUES SECTION +# +## The cluster name. A new cluster of this name will be automatically registered at StackRox Central +## when deploying this Helm chart. Make sure that this name is unique among the set of secured clusters. +#clusterName: null +# +## To change the cluster name, confirm the new cluster name in this field. It should match the `clusterName` value. +## You don't need to change this unless you upgrade and change the value for clusterName. +## In this case, set it to the new value of clusterName. This option exists to prevent you from accidentally +## creating a new cluster with a different name. +#confirmNewClusterName: null +# +## Custom labels associated with a secured cluster in StackRox. +#clusterLabels: {} +# +## The gRPC endpoint for accessing StackRox Central. +#centralEndpoint: central.{{ .Release.Namespace }}.svc:443 +# +## A dictionary of additional CA certificates to include (PEM encoded). +## For example: +## additionalCAs: +## acme-labs-ca.pem: | +## -----BEGIN CERTIFICATE----- +## [...] +## -----END CERTIFICATE----- +#additionalCAs: null +# +# Specify `true` to create the `sensor-upgrader` account. By default, the StackRox Kubernetes +# Security Platform creates a service account called `sensor-upgrader` in each secured cluster. +# This account is highly privileged but is only used during upgrades. If you don’t create this +# account, you will have to complete future upgrades manually if the Sensor doesn’t have enough +# permissions. See +# [Enable automatic upgrades for secured clusters](https://help.stackrox.com/docs/configure-stackrox/enable-automatic-upgrades/) +# for more information. +# Note that auto-upgrades for Helm-managed clusters are disabled. +#createUpgraderServiceAccount: false +# +## Configuration for image pull secrets. +## These should usually be set via the command line when running `helm install`, e.g., +## helm install --set imagePullSecrets.username=myuser --set imagePullSecrets.password=mypass, +## or be stored in a separate YAML-encoded secrets file. +#imagePullSecrets: +# +# # If no image pull secrets are provided, an installation would usually fail. In order to +# # prevent it from failing, this option must explicitly be set to true. +# allowNone: false +# +# # If there exist available image pull secrets in the cluster that are managed separately, +# # set this value to the list of the respective secret names. While it is recommended to +# # record the secret names in a persisted YAML file, providing a single string containing +# # a comma-delimited list of secret names is also supported, for easier interaction with +# # --set. +# useExisting: [] +# +# # Whether to import any secrets from the default service account existing in the StackRox +# # namespace. The default service account often contains "standard" image pull secrets that +# # should be used by default for image pulls, hence this defaults to true. Only has an effect +# # if server-side lookups are enabled. +# useFromDefaultServiceAccount: true +# +## Settings regarding the installation environment +#env: +# # Treat the environment as an OpenShift cluster. Leave this unset to use auto-detection +# # based on available API resources on the server. +# # Set it to true to auto-detect the OpenShift version, otherwise set it explicitly. +# # Possible values: null, false, true, 3, 4 +# openshift: null +# +# # Treat the environment as Istio-enabled. Leave this unset to use auto-detection based on +# # available API resources on the server. +# # Possible values: null, false, true +# istio: null +# +## PEM-encoded StackRox Service CA certificate. +#ca: +# cert: null +# +## Image configuration +#image: +# # The image registry to use. Unless overridden in the more specific configs, this +# # determines the base registry for each image referenced in this config file. +# registry: my.image-registry.io +# +# # Configuration for the `main` image -- used by Sensor, Admission Control, Compliance. +# main: +# registry: null # if set to null, use `image.registry` +# name: main # the final image name is composed of the registry and the name, plus the tag below +# tag: null # should be left as null - will get picked up from the Chart version. +# fullRef: null # you can set a full image reference such as stackrox.io/main:1.2.3.4 here, but this is not +# # recommended. +# # The default pull policy for this image. Can be overridden for each individual service. +# pullPolicy: IfNotPresent +# +# # Configuration for the `collector` image -- used by Collector. +# collector: +# registry: null +# name: collector +# tag: null +# fullRef: null +# pullPolicy: IfNotPresent +# +## Sensor specific configuration. +#sensor: +# +# # Kubernetes image pull policy for Sensor. +# imagePullPolicy: IfNotPresent +# +# # Resource configuration for the sensor container. +# resources: +# requests: +# memory: "4Gi" +# cpu: "2" +# limits: +# memory: "8Gi" +# cpu: "4" +# +# # Settings for the internal service-to-service TLS certificate used by Sensor. +# serviceTLS: +# cert: null +# key: null +# +# # Use a nodeSelector for sensor +# nodeSelector +# environment: production +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # Sensor is single-homed, so avoid preemptible nodes. +# - weight: 100 +# preference: +# matchExpressions: +# - key: cloud.google.com/gke-preemptible +# operator: NotIn +# values: +# - "true" +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/infra +# operator: Exists +# - weight: 25 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/compute +# operator: Exists +# # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in +# # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/master +# operator: DoesNotExist +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/control-plane +# operator: DoesNotExist +# +# # Address of the Sensor endpoint including port number. No trailing slash. +# # Rarely needs to be changed. +# endpoint: sensor.stackrox.svc:443 +# +## Admission Control specific configuration. +#admissionControl: +# +# # This setting controls whether the cluster is configured to contact the StackRox +# # Kubernetes Security Platform with `AdmissionReview` requests for create events on +# # Kubernetes objects. +# listenOnCreates: false +# +# # This setting controls whether the cluster is configured to contact the StackRox Kubernetes +# # Security Platform with `AdmissionReview` requests for update events on Kubernetes objects. +# listenOnUpdates: false +# +# # This setting controls whether the cluster is configured to contact the StackRox +# # Kubernetes Security Platform with `AdmissionReview` requests for update Kubernetes events +# # like exec and portforward. +# # +# # Defaults to `false` on OpenShift, to `true` otherwise. +# listenOnEvents: true +# +# # Use a nodeSelector for admission control pods +# nodeSelector +# environment: production +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # node-role.kubernetes.io/master is replaced by node-role.kubernetes.io/control-plane from certain version +# # of k8s. We apply both to be compatible with any k8s version. +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/master +# operator: Exists +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/control-plane +# operator: Exists +# podAntiAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 60 +# podAffinityTerm: +# topologyKey: "kubernetes.io/hostname" +# labelSelector: +# matchLabels: +# app: admission-control +# +# # Dynamic part of the configuration which is retrieved from Central and can be modified through +# # the frontend. +# dynamic: +# +# # It controls whether the StackRox Kubernetes Security Platform evaluates policies for object +# # updates; if it’s disabled, all `AdmissionReview` requests are automatically accepted. You must +# # specify `listenOnUpdates` as `true` for this to work. +# enforceOnUpdates: false +# +# # Controls whether the StackRox Kubernetes Security Platform evaluates policies. +# # If disabled, all AdmissionReview requests are automatically accepted. You must specify +# # `listenOnCreates` as `true` for this to work. +# enforceOnCreates: false +# +# scanInline: false +# +# # If enabled, bypassing the Admission Controller is disabled. +# disableBypass: false +# +# # The maximum time in seconds, the StackRox Kubernetes Security Platform should wait while +# # evaluating admission review requests. Use it to set request timeouts when you enable image scanning. +# # If the image scan runs longer than the specified time, the StackRox Kubernetes Security Platform +# # accepts the request. Other enforcement options, such as scaling the deployment to zero replicas, +# # are still applied later if the image violates applicable policies. +# timeout: 3 +# +# # Kubernetes image pull policy for Admission Control. +# imagePullPolicy: IfNotPresent +# +# # Resource configuration for the Admission Control container. +# resources: +# requests: +# memory: "100Mi" +# cpu: "50m" +# limits: +# memory: "500Mi" +# cpu: "500m" +# +# # Replicas configures the replicas of the admission controller pod. +# replicas: 3 +# +# # Settings for the internal service-to-service TLS certificate used by Admission Control. +# serviceTLS: +# cert: null +# key: null +# +## Collector specific configuration. +#collector: +# +# # Collection method to use. Can be one of: +# # - EBPF +# # - CORE_BPF +# # - NO_COLLECTION +# collectionMethod: EBPF +# +# # Configure usage of taint tolerations. If `false`, tolerations are applied to collector, +# # and the collector pods can schedule onto all nodes with taints. If `true`, no tolerations +# # are applied, and the collector pods won't scheduled onto nodes with taints. +# disableTaintTolerations: false +# +# # Configure whether slim Collector images should be used or not. Using slim Collector images +# # requires Central to provide the matching kernel module or eBPF probe. If you are running +# # the StackRox Kubernetes Security Platform in offline mode, you must download a kernel support +# # package from [stackrox.io](https://install.stackrox.io/collector/support-packages/index.html) +# # and upload it to Central for slim Collectors to function. Otherwise, you must ensure that +# # Central can access the online probe repository hosted at https://collector-modules.stackrox.io/. +# slimMode: false +# +# # Kubernetes image pull policy for Collector. +# imagePullPolicy: IfNotPresent +# +# # Resource configuration for the Collector container. +# resources: +# requests: +# memory: "320Mi" +# cpu: "50m" +# limits: +# memory: "1Gi" +# cpu: "750m" +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - operator: "Exists" +# +# complianceImagePullPolicy: IfNotPresent +# +# # Resource configuration for the Compliance container. +# complianceResources: +# requests: +# memory: "10Mi" +# cpu: "10m" +# limits: +# memory: "2Gi" +# cpu: "1" +# +# # Resource configuration for the Node Inventory container. +# nodeScanningResources: +# requests: +# memory: "10Mi" +# cpu: "10m" +# limits: +# memory: "500Mi" +# cpu: "1" +# +# # Settings for the internal service-to-service TLS certificate used by Collector. +# serviceTLS: +# cert: null +# key: null +# +# # Settings configuring the ingestion of audit logs: +# auditLogs: +# # Disable audit log collection. This setting defaults to false on OpenShift 4 clusters. On all other cluster types, +# # it defaults to true, and setting it to false will result in an error. +# disableCollection: false +# +# # Customization Settings. +# # The following allows specifying custom Kubernetes metadata (labels and annotations) +# # for all objects instantiated by this Helm chart, as well as additional pod labels, +# # pod annotations, and container environment variables for workloads. +# # The configuration is hierarchical, in the sense that metadata that is defined at a more +# # generic scope (e.g., for all objects) can be overridden by metadata defined at a narrower +# # scope (e.g., only for the sensor deployment). +# customize: +# # Extra metadata for all objects. +# labels: +# my-label-key: my-label-value +# annotations: +# my-annotation-key: my-annotation-value +# +# # Extra pod metadata for all objects (only has an effect for workloads, i.e., deployments). +# podLabels: +# my-pod-label-key: my-pod-label-value +# podAnnotations: +# my-pod-annotation-key: my-pod-annotation-value +# +# # Extra environment variables for all containers in all objects. +# envVars: +# MY_ENV_VAR_NAME: MY_ENV_VAR_VALUE +# +# # Extra metadata for the Sensor deployment only. +# sensor: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the collector daemon set only. +# collector: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the admission control only. +# admission-control: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the compliance only. +# compliance: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for all other objects. The keys in the following map can be +# # an object name of the form "service/central-loadbalancer", or a reference to all +# # objects of a given type in the form "service/*". The values under each key +# # are the five metadata overrides (labels, annotations, podLabels, podAnnotations, envVars) +# # as specified above, though only the first two will be relevant for non-workload +# # object types. +# other: +# "service/*": +# labels: {} +# annotations: {} +# +# # EXPERT SETTINGS +# # The following settings should only be changed if you know very well what you are doing. +# # The scenarios in which these are required are generally not supported. +# +# # Set allowNonstandardNamespace=true if you are deploying into a namespace other than +# # "stackrox". This has been observed to work in some case, but is not generally supported. +# allowNonstandardNamespace: false +# +# # Set allowNonstandardReleaseName=true if you are deploying with a release name other than +# # the default "stackrox-central-services". This has been observed to work in some cases, +# # but is not generally supported. +# allowNonstandardReleaseName: false +# +# +#meta: +# # This is a dictionary from file names to contents that can be used to inject files that +# # would usually be included via .Files.Get into the chart rendering. +# fileOverrides: {} +# +# # This configuration section allows overriding settings that would be inferred from the +# # running API server. +# apiServer: +# # The Kubernetes version running on the API server. This is used for auto-detection +# # of the platform. +# version: null +# # The list of available API resources on the server, in the form of "apps/v1" or +# # "apps/v1/Deployment". This is used to detect environment capabilities. +# overrideAPIResources: null +# # A list of extra API resources that should be assumed to exist on the API server. This +# # can be used in conjunction with both data obtained from the API server, or data set +# # via `overrideAPIResources`. +# extraAPIResources: [] +# +#monitoring: +# # Enables integration with OpenShift platform monitoring. +# openshift: +# enabled: true diff --git a/4.3.8/secured-cluster-services/values-scanner.yaml.example b/4.3.8/secured-cluster-services/values-scanner.yaml.example new file mode 100644 index 0000000..c422153 --- /dev/null +++ b/4.3.8/secured-cluster-services/values-scanner.yaml.example @@ -0,0 +1,92 @@ +# # NOTE: +# # The Scanner is only available in the secured clusters on the OpenShift Container Platform. +# +# # Public configuration options for the StackRox Scanner: +# # When installing the Secured Cluster chart, a slim scanner mode is deployed with reduced image caching. +# # To run the scanner in the secured cluster, you must connect the Scanner to Sensor. +# +# # WARNING: +# # If deployed in the same namespace with Central it is only supported to install Scanner as part of Central's installation. +# # Sensor will use the existing Scanner to scan for local images. +# +# Image configuration for scanner: +# # For a complete example, see the `values-public.yaml.example` file. +# image: +# # Configuration for the `scanner` image that is used by Scanner. +# scanner: +# registry: null +# name: scanner-slim +# tag: null +# fullRef: null +# +# scanner: +# # disable=false Deploys a StackRox Scanner in the secured cluster to allow scanning images +# # from the OpenShift Container Platform cluster's local registries. +# disable: false +# +# # The number of replicas for the Scanner deployment. If autoscaling is enabled (see below), +# # this determines the initial number of replicas. +# replicas: 3 +# +# # The log level for the scanner deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce StackRox Scanner to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-scanner +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# # If you want to enforce StackRox Scanner DB to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner DB can only be scheduled on Nodes with the +# # given label. +# dbNodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-scanner-db +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# dbTolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# # Configuration for autoscaling the Scanner deployment. +# autoscaling: +# # disable=true causes autoscaling to be disabled. All other settings in this section +# # will have no effect. +# disable: false +# # The minimum number of replicas for autoscaling. The following value is the default. +# minReplicas: 2 +# # The maximum number of replicas for autoscaling. The following value is the default. +# maxReplicas: 5 +# +# # Custom resource overrides for the Scanner deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "4Gi" +# cpu: "2000m" +# +# # Custom resource overrides for the Scanner DB deployment. +# dbResources: +# limits: +# cpu: "2000m" +# memory: "4Gi" +# requests: +# cpu: "200m" +# memory: "200Mi" diff --git a/4.3.8/secured-cluster-services/values.yaml b/4.3.8/secured-cluster-services/values.yaml new file mode 100644 index 0000000..3297a22 --- /dev/null +++ b/4.3.8/secured-cluster-services/values.yaml @@ -0,0 +1,9 @@ +## StackRox Secured Cluster Services chart +## values.yaml +## +## This file contains no values. In particular, you should NOT modify this file; instead, +## create your own configuration file and pass it to `helm` via the `-f` parameter. +## For this, you can use the files `values-private.yaml.example` and `values-public.yaml.example` +## that are part of the chart as a blueprint. +## +## Please also consult README.md for a list of available configuration options. diff --git a/README.md b/README.md index fa067cb..a9edc35 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Latest version: 4.4.2](https://img.shields.io/badge/Latest%20version-4.4.2-green.svg)][Latest version] +[![Latest version: 3.0.55.0](https://img.shields.io/badge/Latest%20version-3.0.55.0-green.svg)][Latest version] # Helm charts for the StackRox Kubernetes Security Platform @@ -21,10 +21,10 @@ Afterwards, you can update, download, and install the available charts. For exam ## Installation For instructions on how to install the StackRox Kubernetes Security Platform with these Helm charts, -see [Quick Start (Helm)](https://github.com/stackrox/stackrox#quick-installation-using-helm). +see [Quick Start (Helm)](https://github.com/stackrox/stackrox#quick-installation-via-helm). -To install ACS, follow the [OpenShift docs Helm quick Install Guide](https://docs.openshift.com/acs/installing/installing_other/install-central-other.html#install-using-helm-no-customizations-other). +To install ACS, follow the [OpenShift docs Helm quick Install Guide](https://docs.openshift.com/acs/installing/installing_helm/install-helm-quick.html). ## Included charts @@ -38,7 +38,7 @@ The StackRox Kubernetes Security Platform Helm charts repository includes the fo The Helm chart to install StackRox Central is called `stackrox-central-services`. The installation can be customized to your needs. Please consult the documentation at OpenShift docs for detailed configuration options: -[Configure the central-services Helm chart](https://docs.openshift.com/acs/installing/installing_other/install-central-other.html#install-using-helm-customizations-other) +[Configure the central-services Helm chart](https://docs.openshift.com/acs/installing/installing_helm/install-helm-customization.html#configure-central-services-helm-chart) ### Secured cluster services chart @@ -46,7 +46,7 @@ The chart to install per-cluster and per-node components of StackRox is called ` The installation can be customized to your needs. Consult the OpenShift docs for detailed configuration options: [Configuring the secured-cluster-services Helm chart -](https://docs.openshift.com/acs/installing/installing_other/install-secured-cluster-other.html#configure-secured-cluster-services-helm-chart-customizations-other) +](https://docs.openshift.com/acs/installing/installing_helm/install-helm-customization.html#configure-secured-cluster-services-helm-chart) ## License @@ -55,4 +55,4 @@ Helm charts for the [StackRox Kubernetes Security Platform](https://www.stackrox licensed under [Apache License 2.0](./LICENSE). -[Latest version]: ./4.4.2/ +[Latest version]: ./3.0.55.0/ diff --git a/latest b/latest index 7b224f9..8a44bb6 120000 --- a/latest +++ b/latest @@ -1 +1 @@ -./4.4.2/ \ No newline at end of file +./3.0.50.1/ \ No newline at end of file diff --git a/opensource/index.yaml b/opensource/index.yaml index d42654b..ade1f2e 100644 --- a/opensource/index.yaml +++ b/opensource/index.yaml @@ -3,7 +3,7 @@ entries: stackrox-central-services: - apiVersion: v2 appVersion: 4.4.2 - created: "2024-05-21T15:22:55.146761912Z" + created: "2024-06-06T18:03:17.03432772Z" description: Helm Chart for StackRox Central Service digest: 53dacaa46c90c0a34653202a7baf5926305ad148401db3f0b29d715508f7066e icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -14,7 +14,7 @@ entries: version: 400.4.2 - apiVersion: v2 appVersion: 4.4.1 - created: "2024-05-21T15:22:55.143944297Z" + created: "2024-06-06T18:03:17.032142194Z" description: Helm Chart for StackRox Central Service digest: 74b04983a9eed1eda6fbfa1a621d36e69df48e0cfaebc7d2d4f6b09384bbbecd icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -25,7 +25,7 @@ entries: version: 400.4.1 - apiVersion: v2 appVersion: 4.4.0 - created: "2024-05-21T15:22:55.141789049Z" + created: "2024-06-06T18:03:17.03000689Z" description: Helm Chart for StackRox Central Service digest: d556297e7cdac29233554964cbe05ea8974bb6f230260a89b118d33559c16389 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -34,9 +34,20 @@ entries: urls: - stackrox-central-services-400.4.0.tgz version: 400.4.0 + - apiVersion: v2 + appVersion: 4.3.8 + created: "2024-06-06T18:03:17.027812777Z" + description: Helm Chart for StackRox Central Service + digest: c4627b50d0df1ec9680b6c342d625f07a33a63ff0d6c2865a276d92c61a2bc02 + icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png + name: stackrox-central-services + type: application + urls: + - stackrox-central-services-400.3.8.tgz + version: 400.3.8 - apiVersion: v2 appVersion: 4.3.7 - created: "2024-05-21T15:22:55.139582814Z" + created: "2024-06-06T18:03:17.025502046Z" description: Helm Chart for StackRox Central Service digest: 40d433c4a67a3d2068d085bf0e94316e5793e1eefdda756262e0d180c302c018 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -47,7 +58,7 @@ entries: version: 400.3.7 - apiVersion: v2 appVersion: 4.3.6 - created: "2024-05-21T15:22:55.137815527Z" + created: "2024-06-06T18:03:17.023751633Z" description: Helm Chart for StackRox Central Service digest: b0787153a80155016c3af7d752f4aed60696beb9bb395c5dba52316fd4ce837b icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -58,7 +69,7 @@ entries: version: 400.3.6 - apiVersion: v2 appVersion: 4.3.5 - created: "2024-05-21T15:22:55.135375178Z" + created: "2024-06-06T18:03:17.022039832Z" description: Helm Chart for StackRox Central Service digest: a33d5754c78eca005e9a32a489fe8cb6a026f8c2af6fe146466e4f7a5f5161e8 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -69,7 +80,7 @@ entries: version: 400.3.5 - apiVersion: v2 appVersion: 4.3.4 - created: "2024-05-21T15:22:55.133597421Z" + created: "2024-06-06T18:03:17.020301642Z" description: Helm Chart for StackRox Central Service digest: d0811c842cae01e7d515b666ed3559b9c7b3abea5e4658202a4da10da4c5837b icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -80,7 +91,7 @@ entries: version: 400.3.4 - apiVersion: v2 appVersion: 4.3.3 - created: "2024-05-21T15:22:55.131872984Z" + created: "2024-06-06T18:03:17.01857329Z" description: Helm Chart for StackRox Central Service digest: d25248716307dbc52b36e0d381eb0906f5732f5b5e60f042de7508b0a6268239 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -91,7 +102,7 @@ entries: version: 400.3.3 - apiVersion: v2 appVersion: 4.3.2 - created: "2024-05-21T15:22:55.130104905Z" + created: "2024-06-06T18:03:17.016172521Z" description: Helm Chart for StackRox Central Service digest: 27c33b9849b17bdedb056d34bfa5aa2f92d16f2de601658a75b90ab7285d69f9 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -102,7 +113,7 @@ entries: version: 400.3.2 - apiVersion: v2 appVersion: 4.3.1 - created: "2024-05-21T15:22:55.128032226Z" + created: "2024-06-06T18:03:17.014463134Z" description: Helm Chart for StackRox Central Service digest: ef9da4200243f2aeffdbb10d67e43787749d2838c231995d4cee7e6b94774b0c icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -113,7 +124,7 @@ entries: version: 400.3.1 - apiVersion: v2 appVersion: 4.3.0 - created: "2024-05-21T15:22:55.125921642Z" + created: "2024-06-06T18:03:17.012747416Z" description: Helm Chart for StackRox Central Service digest: 0aa9d33c6539190d4e32de0658010b09b312f5ee34b4ef008126a4226b7bc5e2 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -124,7 +135,7 @@ entries: version: 400.3.0 - apiVersion: v2 appVersion: 4.2.5 - created: "2024-05-21T15:22:55.124172879Z" + created: "2024-06-06T18:03:17.010995921Z" description: Helm Chart for StackRox Central Service digest: 2d04e704ea328052b2ae2a828b2dc01aad02f141becfa23c52275e157cc252c9 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -135,7 +146,7 @@ entries: version: 400.2.5 - apiVersion: v2 appVersion: 4.2.4 - created: "2024-05-21T15:22:55.122467258Z" + created: "2024-06-06T18:03:17.009275053Z" description: Helm Chart for StackRox Central Service digest: 85d679bcfadd61ba00e0da009c358aaad2d112707cfd035f44f43b8a7fb9fc39 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -146,7 +157,7 @@ entries: version: 400.2.4 - apiVersion: v2 appVersion: 4.2.3 - created: "2024-05-21T15:22:55.120706803Z" + created: "2024-06-06T18:03:17.00697605Z" description: Helm Chart for StackRox Central Service digest: a192b67fbb898667f1f858a9e75eefb4dc7823693fb4c091140e90b9b389b6fe icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -157,7 +168,7 @@ entries: version: 400.2.3 - apiVersion: v2 appVersion: 4.2.2 - created: "2024-05-21T15:22:55.118242158Z" + created: "2024-06-06T18:03:17.00522742Z" description: Helm Chart for StackRox Central Service digest: 26d896c0ac476e23df0bbe65d8c469874a0379ef2376f75ba41302e8beebc153 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -168,7 +179,7 @@ entries: version: 400.2.2 - apiVersion: v2 appVersion: 4.2.1 - created: "2024-05-21T15:22:55.116501852Z" + created: "2024-06-06T18:03:17.003466787Z" description: Helm Chart for StackRox Central Service digest: 869c4fb79cc6f85f8009bf1a13760fed4acaa0138f47795f255639d9ab4d1947 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -179,7 +190,7 @@ entries: version: 400.2.1 - apiVersion: v2 appVersion: 4.2.0 - created: "2024-05-21T15:22:55.114759972Z" + created: "2024-06-06T18:03:17.001749777Z" description: Helm Chart for StackRox Central Service digest: 33915b7ef1a8b0811d61774e14d7dce5f711eeeb33b5f250db04fd8f10a0ea85 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -190,7 +201,7 @@ entries: version: 400.2.0 - apiVersion: v2 appVersion: 4.1.6 - created: "2024-05-21T15:22:55.108526254Z" + created: "2024-06-06T18:03:16.999260416Z" description: Helm Chart for StackRox Central Service digest: 65814f2b7a4acb3fba232f9395e5cc1779f6059897a5f6a10e912e54b0bf1dc6 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -201,7 +212,7 @@ entries: version: 400.1.6 - apiVersion: v2 appVersion: 4.1.5 - created: "2024-05-21T15:22:55.106313864Z" + created: "2024-06-06T18:03:16.997617604Z" description: Helm Chart for StackRox Central Service digest: 582dfa2a49ce484d7cd55433f78579945057efe6fc571244f9be5b8210fed24e icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -212,7 +223,7 @@ entries: version: 400.1.5 - apiVersion: v2 appVersion: 4.1.4 - created: "2024-05-21T15:22:55.104627649Z" + created: "2024-06-06T18:03:16.995853465Z" description: Helm Chart for StackRox Central Service digest: ab660fdb76a7a71a6bf666269e2b313f03ce81e3eb39f16fa7b0feccafe0fddc icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -223,7 +234,7 @@ entries: version: 400.1.4 - apiVersion: v2 appVersion: 4.1.3 - created: "2024-05-21T15:22:55.102969387Z" + created: "2024-06-06T18:03:16.994202027Z" description: Helm Chart for StackRox Central Service digest: e073f4c37c34c19a793a0c1b741e2ee6c425915c047c98c2358f1cc30421ff50 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -234,7 +245,7 @@ entries: version: 400.1.3 - apiVersion: v2 appVersion: 4.1.2 - created: "2024-05-21T15:22:55.101268815Z" + created: "2024-06-06T18:03:16.992389678Z" description: Helm Chart for StackRox Central Service digest: 3add7559d60bec74a5627d859bdb73f2787e476f3b4d801e81e85835fa44cfcc icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -245,7 +256,7 @@ entries: version: 400.1.2 - apiVersion: v2 appVersion: 4.1.1 - created: "2024-05-21T15:22:55.098988381Z" + created: "2024-06-06T18:03:16.978407678Z" description: Helm Chart for StackRox Central Service digest: c4e11d64ff283573ecd6129e5759f0c20e0e7e18ea5fae2813d20e5c03d5f47d icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -256,7 +267,7 @@ entries: version: 400.1.1 - apiVersion: v2 appVersion: 4.1.0 - created: "2024-05-21T15:22:55.097290574Z" + created: "2024-06-06T18:03:16.976759987Z" description: Helm Chart for StackRox Central Service digest: 9daf73d7e2d5930d4b8dc7730ff167046429ef18cb4b4b6bf1e1d7f51c95223a icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -267,7 +278,7 @@ entries: version: 400.1.0 - apiVersion: v2 appVersion: 4.0.5 - created: "2024-05-21T15:22:55.095639696Z" + created: "2024-06-06T18:03:16.975068955Z" description: Helm Chart for StackRox Central Service digest: 8d30f97407a9103c7f375b8aad6f28858abb1e52c401af5efdfc29f606a0b546 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -278,7 +289,7 @@ entries: version: 400.0.5 - apiVersion: v2 appVersion: 4.0.4 - created: "2024-05-21T15:22:55.093971565Z" + created: "2024-06-06T18:03:16.973385638Z" description: Helm Chart for StackRox Central Service digest: ccb5ca6bfbc0eb7a948bd937eca331175d9c493e0974181aff7185fab75bda9e icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -289,7 +300,7 @@ entries: version: 400.0.4 - apiVersion: v2 appVersion: 4.0.3 - created: "2024-05-21T15:22:55.091683752Z" + created: "2024-06-06T18:03:16.971106609Z" description: Helm Chart for StackRox Central Service digest: 8ee22ceea86c50ca1b25e2e5bbdcd0a8abcf20534b03066fcd333ef2b74ba99c icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -300,7 +311,7 @@ entries: version: 400.0.3 - apiVersion: v2 appVersion: 4.0.2 - created: "2024-05-21T15:22:55.090005021Z" + created: "2024-06-06T18:03:16.969424494Z" description: Helm Chart for StackRox Central Service digest: 76b5ef10625e3f33b1502db29336231f30f78a40873311041abfcc6bb0d802ee icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -311,7 +322,7 @@ entries: version: 400.0.2 - apiVersion: v2 appVersion: 4.0.1 - created: "2024-05-21T15:22:55.088247221Z" + created: "2024-06-06T18:03:16.967701001Z" description: Helm Chart for StackRox Central Service digest: 787d0657cb9c47363d1b15a160a1d77117270e46b7cad81b9764985470c168c8 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -322,7 +333,7 @@ entries: version: 400.0.1 - apiVersion: v2 appVersion: 4.0.0 - created: "2024-05-21T15:22:55.086546679Z" + created: "2024-06-06T18:03:16.966006863Z" description: Helm Chart for StackRox Central Service digest: cb79b0e12e89204dbb9e06e981ebb8ed71a23d90104ccc76ecbf9f573a7c1d89 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -333,7 +344,7 @@ entries: version: 400.0.0 - apiVersion: v2 appVersion: 3.74.9 - created: "2024-05-21T15:22:55.193050434Z" + created: "2024-06-06T18:03:17.079936015Z" description: Helm Chart for StackRox Central Service digest: 29580407a9a36a612fdb5c083a942cad1390fbb43e62844dad054c6a5b0543f0 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -344,7 +355,7 @@ entries: version: 74.9.0 - apiVersion: v2 appVersion: 3.74.8 - created: "2024-05-21T15:22:55.191259682Z" + created: "2024-06-06T18:03:17.078154594Z" description: Helm Chart for StackRox Central Service digest: 999594d1dc60d5e3770792312311470c090af9fb18513036af41e57b772761c3 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -355,7 +366,7 @@ entries: version: 74.8.0 - apiVersion: v2 appVersion: 3.74.7 - created: "2024-05-21T15:22:55.189422283Z" + created: "2024-06-06T18:03:17.07631859Z" description: Helm Chart for StackRox Central Service digest: 3208a18bf3570b706088a4964008f23ca4b3fca4a31da699c020c08494aa6589 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -366,7 +377,7 @@ entries: version: 74.7.0 - apiVersion: v2 appVersion: 3.74.6 - created: "2024-05-21T15:22:55.187623616Z" + created: "2024-06-06T18:03:17.074520428Z" description: Helm Chart for StackRox Central Service digest: 27caeaa0f03c39534131b3ea9209f7043cd3730fe6460d93b7bc768cc0af8b92 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -377,7 +388,7 @@ entries: version: 74.6.0 - apiVersion: v2 appVersion: 3.74.5 - created: "2024-05-21T15:22:55.185270091Z" + created: "2024-06-06T18:03:17.072100281Z" description: Helm Chart for StackRox Central Service digest: e3f09e301e9becb613e2096c5965de0642467ef3beb2e2d321eb507518cfbbfe icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -388,7 +399,7 @@ entries: version: 74.5.0 - apiVersion: v2 appVersion: 3.74.4 - created: "2024-05-21T15:22:55.183489919Z" + created: "2024-06-06T18:03:17.07028656Z" description: Helm Chart for StackRox Central Service digest: 3c3c962f26bb1afd7d01063348e869352e18380899ba988c9a29d98f507ac0ec icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -399,7 +410,7 @@ entries: version: 74.4.0 - apiVersion: v2 appVersion: 3.74.3 - created: "2024-05-21T15:22:55.181659944Z" + created: "2024-06-06T18:03:17.068464933Z" description: Helm Chart for StackRox Central Service digest: 3480735d019cf9147e39e5eb5e30b26352b57b97ddfea70e18d8cfe525ba4b31 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -410,7 +421,7 @@ entries: version: 74.3.0 - apiVersion: v2 appVersion: 3.74.2 - created: "2024-05-21T15:22:55.179828825Z" + created: "2024-06-06T18:03:17.06663961Z" description: Helm Chart for StackRox Central Service digest: b92aaa2f087c0c8ca06dd49960a55500c1ac711856b4b4aa945a849bdc7d474e icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -421,7 +432,7 @@ entries: version: 74.2.0 - apiVersion: v2 appVersion: 3.74.1 - created: "2024-05-21T15:22:55.177306811Z" + created: "2024-06-06T18:03:17.064544758Z" description: Helm Chart for StackRox Central Service digest: 487b016f61a934d62ccf06650289f109ea96bcdc3ae424aa3740485abadf65ad icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -432,7 +443,7 @@ entries: version: 74.1.0 - apiVersion: v2 appVersion: 3.74.0 - created: "2024-05-21T15:22:55.175522993Z" + created: "2024-06-06T18:03:17.062290542Z" description: Helm Chart for StackRox Central Service digest: 97b02189b39879635556453fcdc1c2707d196b65fa5b0c0098928aa24df8127a icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -443,7 +454,7 @@ entries: version: 74.0.0 - apiVersion: v2 appVersion: 3.73.5 - created: "2024-05-21T15:22:55.173729185Z" + created: "2024-06-06T18:03:17.060481099Z" description: Helm Chart for StackRox Central Service digest: 54bf152552c83b76dedaeac3109bff16ff07ab25bd9c7cb3fcf3eff996dc4a00 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -454,7 +465,7 @@ entries: version: 73.5.0 - apiVersion: v2 appVersion: 3.73.4 - created: "2024-05-21T15:22:55.171892427Z" + created: "2024-06-06T18:03:17.058714355Z" description: Helm Chart for StackRox Central Service digest: 80651037b1be3e7f49eb97fdda3f96b423021187aa1f40eba3307a105390a5cc icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -465,7 +476,7 @@ entries: version: 73.4.0 - apiVersion: v2 appVersion: 3.73.3 - created: "2024-05-21T15:22:55.169356708Z" + created: "2024-06-06T18:03:17.056919348Z" description: Helm Chart for StackRox Central Service digest: 7fc78ddf8b1f8178d788df2d0e7d7c8845fb6190cd0399aa14140c320f541337 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -476,7 +487,7 @@ entries: version: 73.3.0 - apiVersion: v2 appVersion: 3.73.2 - created: "2024-05-21T15:22:55.167583078Z" + created: "2024-06-06T18:03:17.054518779Z" description: Helm Chart for StackRox Central Service digest: 8aa72d09fc9e4625e7429cada53a779e11b6a81fb4902a1c95b697e51165815b icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -487,7 +498,7 @@ entries: version: 73.2.0 - apiVersion: v2 appVersion: 3.73.1 - created: "2024-05-21T15:22:55.165807705Z" + created: "2024-06-06T18:03:17.052745243Z" description: Helm Chart for StackRox Central Service digest: cc929f82add69b661161ebdcd3dae0e007a1c55d6860686db113e7d0cea72cfd icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -498,7 +509,7 @@ entries: version: 73.1.0 - apiVersion: v2 appVersion: 3.73.0 - created: "2024-05-21T15:22:55.163984252Z" + created: "2024-06-06T18:03:17.050944726Z" description: Helm Chart for StackRox Central Service digest: 59c30250551c5fddbdd5f32683b23538e9aad120bcf095d04c943989c56adef0 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -509,7 +520,7 @@ entries: version: 73.0.0 - apiVersion: v2 appVersion: 3.72.4 - created: "2024-05-21T15:22:55.161495499Z" + created: "2024-06-06T18:03:17.049171821Z" description: Helm Chart for StackRox Central Service digest: 33c96fa6d02a45d8f3e189ffbe9fffb54e1979fc84d9d4cc2bfffb06048f8b60 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -520,7 +531,7 @@ entries: version: 72.4.0 - apiVersion: v2 appVersion: 3.72.3 - created: "2024-05-21T15:22:55.159927787Z" + created: "2024-06-06T18:03:17.047591085Z" description: Helm Chart for StackRox Central Service digest: c9056c0972ab0c24c91900a91072528008b6302a8e066bff239e0e78cef2a4c5 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -531,7 +542,7 @@ entries: version: 72.3.0 - apiVersion: v2 appVersion: 3.72.2 - created: "2024-05-21T15:22:55.15838368Z" + created: "2024-06-06T18:03:17.045443927Z" description: Helm Chart for StackRox Central Service digest: 41e069ecf8acd9b6b17399f8e3336e530eac73f0f988387e66d506e40c9486de icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -542,7 +553,7 @@ entries: version: 72.2.0 - apiVersion: v2 appVersion: 3.72.1 - created: "2024-05-21T15:22:55.156808374Z" + created: "2024-06-06T18:03:17.043887376Z" description: Helm Chart for StackRox Central Service digest: dffec915f18f9f0c88f7609ad6fb415e281557bf8695357dc1cecc0b4f1a8936 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -553,7 +564,7 @@ entries: version: 72.1.0 - apiVersion: v2 appVersion: 3.72.0 - created: "2024-05-21T15:22:55.155205155Z" + created: "2024-06-06T18:03:17.042351304Z" description: Helm Chart for StackRox Central Service digest: 8be952be40ef29b13fc95bac4d6dff5b9289d34e32a32497e8465b4c1cce661e icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -564,7 +575,7 @@ entries: version: 72.0.0 - apiVersion: v2 appVersion: 3.71.3 - created: "2024-05-21T15:22:55.152779823Z" + created: "2024-06-06T18:03:17.040817065Z" description: Helm Chart for StackRox Central Clusters digest: df3fca54fb637426e3c895d7356b7dfb95ed64384e005919cfa8de571d48a20d icon: https://www.stackrox.com/img/logo.svg @@ -575,7 +586,7 @@ entries: version: 71.3.0 - apiVersion: v2 appVersion: 3.71.2 - created: "2024-05-21T15:22:55.15121141Z" + created: "2024-06-06T18:03:17.039331216Z" description: Helm Chart for StackRox Central Clusters digest: 7ff76bf8dc53b249ab1d9c61fd203f834777a39346e217e18862cb6b47808204 icon: https://www.stackrox.com/img/logo.svg @@ -586,7 +597,7 @@ entries: version: 71.2.0 - apiVersion: v2 appVersion: 3.71.0 - created: "2024-05-21T15:22:55.149679766Z" + created: "2024-06-06T18:03:17.037858843Z" description: Helm Chart for StackRox Central Clusters digest: 22115098ea95e326a08063c0fd5089647d729e58d6d668a9ad22841055f17498 icon: https://www.stackrox.com/img/logo.svg @@ -597,7 +608,7 @@ entries: version: 71.0.0 - apiVersion: v2 appVersion: 3.70.0 - created: "2024-05-21T15:22:55.148214267Z" + created: "2024-06-06T18:03:17.035767893Z" description: Helm Chart for StackRox Central Clusters digest: db1c6b84de673bcf72f41b21059b020ad91bd116ddb38772fc0292296e484e5f icon: https://www.stackrox.com/img/logo.svg @@ -609,7 +620,7 @@ entries: stackrox-secured-cluster-services: - apiVersion: v2 appVersion: 4.4.2 - created: "2024-05-21T15:22:55.247639129Z" + created: "2024-06-06T18:03:17.136276133Z" description: Helm Chart for StackRox Secured Clusters digest: fa35596e1378e4b66b17ae04ad7b7688c54ba9df750ee724b82d25e2fbc199e3 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -620,7 +631,7 @@ entries: version: 400.4.2 - apiVersion: v2 appVersion: 4.4.1 - created: "2024-05-21T15:22:55.245434348Z" + created: "2024-06-06T18:03:17.133657374Z" description: Helm Chart for StackRox Secured Clusters digest: 626c774a39b015273edad42da291d63d10ea595b442baf7655600817726046e3 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -631,7 +642,7 @@ entries: version: 400.4.1 - apiVersion: v2 appVersion: 4.4.0 - created: "2024-05-21T15:22:55.243458167Z" + created: "2024-06-06T18:03:17.131652996Z" description: Helm Chart for StackRox Secured Clusters digest: c26f441d9ccd3a18d659838f80196150462113dfeacbfdedef8fafffca2a7864 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -640,9 +651,20 @@ entries: urls: - stackrox-secured-cluster-services-400.4.0.tgz version: 400.4.0 + - apiVersion: v2 + appVersion: 4.3.8 + created: "2024-06-06T18:03:17.129696738Z" + description: Helm Chart for StackRox Secured Clusters + digest: 90637e07e07e2a103143b9fa4d35bdb24ff28dbe52235244151d361597442a3f + icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png + name: stackrox-secured-cluster-services + type: application + urls: + - stackrox-secured-cluster-services-400.3.8.tgz + version: 400.3.8 - apiVersion: v2 appVersion: 4.3.7 - created: "2024-05-21T15:22:55.240885384Z" + created: "2024-06-06T18:03:17.128033798Z" description: Helm Chart for StackRox Secured Clusters digest: 64f1166523cdb06d635c965510fc4f24f7aca7ce64147eb864200c9bc0153dde icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -653,7 +675,7 @@ entries: version: 400.3.7 - apiVersion: v2 appVersion: 4.3.6 - created: "2024-05-21T15:22:55.239256096Z" + created: "2024-06-06T18:03:17.125835775Z" description: Helm Chart for StackRox Secured Clusters digest: aedf87ef94743542aa61d38c34e8f37f0896c8795ae1389b460f729d4590e22c icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -664,7 +686,7 @@ entries: version: 400.3.6 - apiVersion: v2 appVersion: 4.3.5 - created: "2024-05-21T15:22:55.237608263Z" + created: "2024-06-06T18:03:17.12418604Z" description: Helm Chart for StackRox Secured Clusters digest: fd402064a38aff3fb04f96b0bb07be2f224e0fc4e82b6b8f2e78c244be93e74f icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -675,7 +697,7 @@ entries: version: 400.3.5 - apiVersion: v2 appVersion: 4.3.4 - created: "2024-05-21T15:22:55.235974126Z" + created: "2024-06-06T18:03:17.122562454Z" description: Helm Chart for StackRox Secured Clusters digest: aff0c0bbbc6a00774e0ddcec863092338125445937e61fb525d62b33a2defbb9 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -686,7 +708,7 @@ entries: version: 400.3.4 - apiVersion: v2 appVersion: 4.3.3 - created: "2024-05-21T15:22:55.23395078Z" + created: "2024-06-06T18:03:17.120751638Z" description: Helm Chart for StackRox Secured Clusters digest: fb5fb6871823ee2e7d0cb061bacc680cf2595c2f4c33cb6c3d9aa9dc7551b874 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -697,7 +719,7 @@ entries: version: 400.3.3 - apiVersion: v2 appVersion: 4.3.2 - created: "2024-05-21T15:22:55.232128509Z" + created: "2024-06-06T18:03:17.11908464Z" description: Helm Chart for StackRox Secured Clusters digest: b35677810e0b05f32171ea6de3048b34856364627f19caba1501c0b8eccda113 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -708,7 +730,7 @@ entries: version: 400.3.2 - apiVersion: v2 appVersion: 4.3.1 - created: "2024-05-21T15:22:55.230505253Z" + created: "2024-06-06T18:03:17.117081528Z" description: Helm Chart for StackRox Secured Clusters digest: dc4c3c3d8719ce7f5027ae33d3a274b665914622db508239c3f0199d254c3396 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -719,7 +741,7 @@ entries: version: 400.3.1 - apiVersion: v2 appVersion: 4.3.0 - created: "2024-05-21T15:22:55.228828696Z" + created: "2024-06-06T18:03:17.115131352Z" description: Helm Chart for StackRox Secured Clusters digest: 4954c026c24cc6b317834f14a55074c42fe8683678c4c6e2cfb00c5d6159caa1 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -730,7 +752,7 @@ entries: version: 400.3.0 - apiVersion: v2 appVersion: 4.2.5 - created: "2024-05-21T15:22:55.227158261Z" + created: "2024-06-06T18:03:17.113514007Z" description: Helm Chart for StackRox Secured Clusters digest: 19f35620417736f762e42cd342e3889bd7bdfb4b22ef322959f47bfa4e3b8ac0 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -741,7 +763,7 @@ entries: version: 400.2.5 - apiVersion: v2 appVersion: 4.2.4 - created: "2024-05-21T15:22:55.225022113Z" + created: "2024-06-06T18:03:17.111854925Z" description: Helm Chart for StackRox Secured Clusters digest: f48032e9479874b0cc60e5a8e96220937f7882d412772f4744a04c715b0dcffc icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -752,7 +774,7 @@ entries: version: 400.2.4 - apiVersion: v2 appVersion: 4.2.3 - created: "2024-05-21T15:22:55.22340075Z" + created: "2024-06-06T18:03:17.110223354Z" description: Helm Chart for StackRox Secured Clusters digest: bc7a3de27ce6bfa2ecdb1ba82ae0453860e9c2197e51948c40d59ce17b0d08a3 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -763,7 +785,7 @@ entries: version: 400.2.3 - apiVersion: v2 appVersion: 4.2.2 - created: "2024-05-21T15:22:55.22176479Z" + created: "2024-06-06T18:03:17.108034092Z" description: Helm Chart for StackRox Secured Clusters digest: b6e110b53a79245180d5489321d29b66def2216602ad4bdc806a45c6d48f70c9 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -774,7 +796,7 @@ entries: version: 400.2.2 - apiVersion: v2 appVersion: 4.2.1 - created: "2024-05-21T15:22:55.219960954Z" + created: "2024-06-06T18:03:17.106373517Z" description: Helm Chart for StackRox Secured Clusters digest: cd0073952b8b268bec0037e8fc4e2b20a04cf3727391fde40f90b2a7d5a72d8d icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -785,7 +807,7 @@ entries: version: 400.2.1 - apiVersion: v2 appVersion: 4.2.0 - created: "2024-05-21T15:22:55.217725822Z" + created: "2024-06-06T18:03:17.104745513Z" description: Helm Chart for StackRox Secured Clusters digest: db306d052b0b6d78e6abf600183f1ea7d72e277bc3d50f29c190409777bc644c icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -796,7 +818,7 @@ entries: version: 400.2.0 - apiVersion: v2 appVersion: 4.1.6 - created: "2024-05-21T15:22:55.216072569Z" + created: "2024-06-06T18:03:17.103080639Z" description: Helm Chart for StackRox Secured Clusters digest: 923407171a8a028052cb58e7bfd8e2e4890b960c9933f890b6d3e4bb5da0acfb icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -807,7 +829,7 @@ entries: version: 400.1.6 - apiVersion: v2 appVersion: 4.1.5 - created: "2024-05-21T15:22:55.214461014Z" + created: "2024-06-06T18:03:17.101453106Z" description: Helm Chart for StackRox Secured Clusters digest: 06c091dcc43736530888509fbe773ce88c63957e7906ec386188f5f6a5224bf3 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -818,7 +840,7 @@ entries: version: 400.1.5 - apiVersion: v2 appVersion: 4.1.4 - created: "2024-05-21T15:22:55.212802522Z" + created: "2024-06-06T18:03:17.099415674Z" description: Helm Chart for StackRox Secured Clusters digest: 3ed39a05313aa817cb5fc312787d33551dffe11b5f0047b43194676889c2b507 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -829,7 +851,7 @@ entries: version: 400.1.4 - apiVersion: v2 appVersion: 4.1.3 - created: "2024-05-21T15:22:55.211144721Z" + created: "2024-06-06T18:03:17.097551959Z" description: Helm Chart for StackRox Secured Clusters digest: 18f5b5f0bd69c21302d276a914a5100a9e5cca72632e101127caddfc6dffecec icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -840,7 +862,7 @@ entries: version: 400.1.3 - apiVersion: v2 appVersion: 4.1.2 - created: "2024-05-21T15:22:55.208892543Z" + created: "2024-06-06T18:03:17.095898968Z" description: Helm Chart for StackRox Secured Clusters digest: 9a404831be82ea5ea6567c838b937760227bb1f98978955c4278383810de18e3 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -851,7 +873,7 @@ entries: version: 400.1.2 - apiVersion: v2 appVersion: 4.1.1 - created: "2024-05-21T15:22:55.207281129Z" + created: "2024-06-06T18:03:17.094291482Z" description: Helm Chart for StackRox Secured Clusters digest: 294d6c05bc0cf4ab89afd38ce6ac16401e7b6ef7b4cc6f41ba276f308a32045f icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -862,7 +884,7 @@ entries: version: 400.1.1 - apiVersion: v2 appVersion: 4.1.0 - created: "2024-05-21T15:22:55.205641852Z" + created: "2024-06-06T18:03:17.092663227Z" description: Helm Chart for StackRox Secured Clusters digest: faad2e105677d7932514830e3993fa9078b5d7cd0fdcea750ab34d66a6f06979 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -873,7 +895,7 @@ entries: version: 400.1.0 - apiVersion: v2 appVersion: 4.0.5 - created: "2024-05-21T15:22:55.204016562Z" + created: "2024-06-06T18:03:17.09097492Z" description: Helm Chart for StackRox Secured Clusters digest: 2f30cebf1819aa81586e36bd41b70867e54e7ae7ccda1f8ca0f78016a22c6382 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -884,7 +906,7 @@ entries: version: 400.0.5 - apiVersion: v2 appVersion: 4.0.4 - created: "2024-05-21T15:22:55.201854616Z" + created: "2024-06-06T18:03:17.088761096Z" description: Helm Chart for StackRox Secured Clusters digest: 6892758562ae3c3480fce3796570da649515b627fe46fed500a333025f4868a0 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -895,7 +917,7 @@ entries: version: 400.0.4 - apiVersion: v2 appVersion: 4.0.3 - created: "2024-05-21T15:22:55.200179703Z" + created: "2024-06-06T18:03:17.087128634Z" description: Helm Chart for StackRox Secured Clusters digest: 407faa33f01752e67a2cfd877f6c0fd3db3800c06a85d37d84fe8394f2f5dc92 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -906,7 +928,7 @@ entries: version: 400.0.3 - apiVersion: v2 appVersion: 4.0.2 - created: "2024-05-21T15:22:55.198566515Z" + created: "2024-06-06T18:03:17.085490099Z" description: Helm Chart for StackRox Secured Clusters digest: 11a52ce31bb3342a466d315b7d63212d03596b6fb876d47be8a5f89f76290d14 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -917,7 +939,7 @@ entries: version: 400.0.2 - apiVersion: v2 appVersion: 4.0.1 - created: "2024-05-21T15:22:55.19691748Z" + created: "2024-06-06T18:03:17.083812653Z" description: Helm Chart for StackRox Secured Clusters digest: 1d8e7a056677b9e3f87d3c2abcfd4ab070a39121c57d456864f65d07098fedcd icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -928,7 +950,7 @@ entries: version: 400.0.1 - apiVersion: v2 appVersion: 4.0.0 - created: "2024-05-21T15:22:55.195268796Z" + created: "2024-06-06T18:03:17.08159665Z" description: Helm Chart for StackRox Secured Clusters digest: e72173415fd130aee22a541a57dad01cb5aaabf041daaeed675ad056313cd2e5 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -939,7 +961,7 @@ entries: version: 400.0.0 - apiVersion: v2 appVersion: 3.74.9 - created: "2024-05-21T15:22:55.29176985Z" + created: "2024-06-06T18:03:17.179084575Z" description: Helm Chart for StackRox Secured Clusters digest: 20b5ebafeb271885cfcd57a5f8b1e4a8f859deeca15f1419f320df20c899d94f icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -950,7 +972,7 @@ entries: version: 74.9.0 - apiVersion: v2 appVersion: 3.74.8 - created: "2024-05-21T15:22:55.290166872Z" + created: "2024-06-06T18:03:17.177492629Z" description: Helm Chart for StackRox Secured Clusters digest: f7f47aa1bb146f6ac80ccc73f1eca69b129cf4845e60a4c3188ef875107f1bb6 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -961,7 +983,7 @@ entries: version: 74.8.0 - apiVersion: v2 appVersion: 3.74.7 - created: "2024-05-21T15:22:55.288518929Z" + created: "2024-06-06T18:03:17.175870285Z" description: Helm Chart for StackRox Secured Clusters digest: f4ccd4f78491695b88816a20ba9299771d992853dabbbba338c7c587f01753e3 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -972,7 +994,7 @@ entries: version: 74.7.0 - apiVersion: v2 appVersion: 3.74.6 - created: "2024-05-21T15:22:55.28650504Z" + created: "2024-06-06T18:03:17.174253031Z" description: Helm Chart for StackRox Secured Clusters digest: c66ce4b6fc54ccbaad47c2455b8f9557079057450f2a64d6633ca20bbf06252f icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -983,7 +1005,7 @@ entries: version: 74.6.0 - apiVersion: v2 appVersion: 3.74.5 - created: "2024-05-21T15:22:55.284581989Z" + created: "2024-06-06T18:03:17.17263746Z" description: Helm Chart for StackRox Secured Clusters digest: d631a15c2b56363f4e402bd802fa0f70bcbbde656b1c882562e38b622149556b icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -994,7 +1016,7 @@ entries: version: 74.5.0 - apiVersion: v2 appVersion: 3.74.4 - created: "2024-05-21T15:22:55.282988047Z" + created: "2024-06-06T18:03:17.170413769Z" description: Helm Chart for StackRox Secured Clusters digest: cb1c78c41c1eb13362cf099cfe813b36a728a51c1a4dbc22a32a68692c234034 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1005,7 +1027,7 @@ entries: version: 74.4.0 - apiVersion: v2 appVersion: 3.74.3 - created: "2024-05-21T15:22:55.281345695Z" + created: "2024-06-06T18:03:17.168818375Z" description: Helm Chart for StackRox Secured Clusters digest: 50ab858bf9b559e435b8ff47fedd993060953d51b7a9750a0fa71385df3260d5 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1016,7 +1038,7 @@ entries: version: 74.3.0 - apiVersion: v2 appVersion: 3.74.2 - created: "2024-05-21T15:22:55.279252085Z" + created: "2024-06-06T18:03:17.167194669Z" description: Helm Chart for StackRox Secured Clusters digest: 295d7b22550ac2d8042c29a3bf601db764183b4666f65739d3ad3d9764bdca80 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1027,7 +1049,7 @@ entries: version: 74.2.0 - apiVersion: v2 appVersion: 3.74.1 - created: "2024-05-21T15:22:55.277554889Z" + created: "2024-06-06T18:03:17.165597232Z" description: Helm Chart for StackRox Secured Clusters digest: 46d92c2b85c4b1ce2cd6b23c9890c00e039502626f42982c66f80cd39819d41a icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1038,7 +1060,7 @@ entries: version: 74.1.0 - apiVersion: v2 appVersion: 3.74.0 - created: "2024-05-21T15:22:55.2759407Z" + created: "2024-06-06T18:03:17.163940845Z" description: Helm Chart for StackRox Secured Clusters digest: b16de939fd234fbd62b3966e2ba0794d5e11e6dd5f782856f4562b0da42eb675 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1049,7 +1071,7 @@ entries: version: 74.0.0 - apiVersion: v2 appVersion: 3.73.5 - created: "2024-05-21T15:22:55.274325599Z" + created: "2024-06-06T18:03:17.161720322Z" description: Helm Chart for StackRox Secured Clusters digest: 05669d6da11df97070af8c402a2cd68a1052ed7457dfe5b5fdd729b30d1c6e3a icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1060,7 +1082,7 @@ entries: version: 73.5.0 - apiVersion: v2 appVersion: 3.73.4 - created: "2024-05-21T15:22:55.272480404Z" + created: "2024-06-06T18:03:17.160086547Z" description: Helm Chart for StackRox Secured Clusters digest: da6ba1c98c51d7238ea44395f1bce8844b7276f932a26580d2e8bdb555c90e03 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1071,7 +1093,7 @@ entries: version: 73.4.0 - apiVersion: v2 appVersion: 3.73.3 - created: "2024-05-21T15:22:55.270374925Z" + created: "2024-06-06T18:03:17.158486755Z" description: Helm Chart for StackRox Secured Clusters digest: 5b50f8880babbdacf1e3e85faa5e23ebc37e80e3c29bbf1e83b75227c7b045e9 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1082,7 +1104,7 @@ entries: version: 73.3.0 - apiVersion: v2 appVersion: 3.73.2 - created: "2024-05-21T15:22:55.26874161Z" + created: "2024-06-06T18:03:17.156830889Z" description: Helm Chart for StackRox Secured Clusters digest: ab4e152523ac791491f832c90b92218597431594953fcf9fda8235aa9bb2c3ce icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1093,7 +1115,7 @@ entries: version: 73.2.0 - apiVersion: v2 appVersion: 3.73.1 - created: "2024-05-21T15:22:55.267138371Z" + created: "2024-06-06T18:03:17.155187095Z" description: Helm Chart for StackRox Secured Clusters digest: 2dc578c3c905b996339b8d5f2f80428c03501a9c9699516dbf12ed11e2091750 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1104,7 +1126,7 @@ entries: version: 73.1.0 - apiVersion: v2 appVersion: 3.73.0 - created: "2024-05-21T15:22:55.265479778Z" + created: "2024-06-06T18:03:17.152875611Z" description: Helm Chart for StackRox Secured Clusters digest: 93e3298b3ee1f96db92b6e23a65591d7a9cb1bffa7871177187815599c8d021a icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1115,7 +1137,7 @@ entries: version: 73.0.0 - apiVersion: v2 appVersion: 3.72.4 - created: "2024-05-21T15:22:55.263270939Z" + created: "2024-06-06T18:03:17.151266272Z" description: Helm Chart for StackRox Secured Clusters digest: e127489a3df22bf5bebbb56cbd6ccc8e9d1f56994cb077be045ca5bbbc1698f4 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1126,7 +1148,7 @@ entries: version: 72.4.0 - apiVersion: v2 appVersion: 3.72.3 - created: "2024-05-21T15:22:55.26163042Z" + created: "2024-06-06T18:03:17.149666631Z" description: Helm Chart for StackRox Secured Clusters digest: dfbd93015a9a8021d53390907dd9e209ca0ded07065cb032e05554eb2a2130ad icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1137,7 +1159,7 @@ entries: version: 72.3.0 - apiVersion: v2 appVersion: 3.72.2 - created: "2024-05-21T15:22:55.260023204Z" + created: "2024-06-06T18:03:17.148031543Z" description: Helm Chart for StackRox Secured Clusters digest: 105e5d5d4318153130d39ca7f65e54a0cdd4d7c56651af3a2da324287f7f412b icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1148,7 +1170,7 @@ entries: version: 72.2.0 - apiVersion: v2 appVersion: 3.72.1 - created: "2024-05-21T15:22:55.258415747Z" + created: "2024-06-06T18:03:17.146406775Z" description: Helm Chart for StackRox Secured Clusters digest: b7d6a675beef0e81bb78e8fbc15b12d9e6182f45918e6a4e9fd8833c6cd8b03e icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1159,7 +1181,7 @@ entries: version: 72.1.0 - apiVersion: v2 appVersion: 3.72.0 - created: "2024-05-21T15:22:55.256264124Z" + created: "2024-06-06T18:03:17.144788148Z" description: Helm Chart for StackRox Secured Clusters digest: 099a3eb3a13c5fc7607d654b0bde4934c6cc5cd8c1c473a3cb64dbf75c540368 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -1170,7 +1192,7 @@ entries: version: 72.0.0 - apiVersion: v2 appVersion: 3.71.3 - created: "2024-05-21T15:22:55.254564896Z" + created: "2024-06-06T18:03:17.142539295Z" description: Helm Chart for StackRox Secured Clusters digest: f05b85662ed91d727ea7ebea0219be5ef0d80e657d69f40b961d5166c88d6292 icon: https://www.stackrox.com/img/logo.svg @@ -1181,7 +1203,7 @@ entries: version: 71.3.0 - apiVersion: v2 appVersion: 3.71.2 - created: "2024-05-21T15:22:55.252995521Z" + created: "2024-06-06T18:03:17.140998343Z" description: Helm Chart for StackRox Secured Clusters digest: 7624e7c16f5f22aaa34ffac654606fb974813f895f312cd1fbd6c103959e9ad0 icon: https://www.stackrox.com/img/logo.svg @@ -1192,7 +1214,7 @@ entries: version: 71.2.0 - apiVersion: v2 appVersion: 3.71.0 - created: "2024-05-21T15:22:55.251452065Z" + created: "2024-06-06T18:03:17.139424851Z" description: Helm Chart for StackRox Secured Clusters digest: eb8decbde7b849b7b21357c0b2812b404b6c08f69e97d2a57478a413223f21e3 icon: https://www.stackrox.com/img/logo.svg @@ -1203,7 +1225,7 @@ entries: version: 71.0.0 - apiVersion: v2 appVersion: 3.70.0 - created: "2024-05-21T15:22:55.249867421Z" + created: "2024-06-06T18:03:17.137880674Z" description: Helm Chart for StackRox Secured Clusters digest: e6ef2cdc20620fab37e0cfd6b5a5646c83e5b1360bd0a7eddd835f5824c16c8a icon: https://www.stackrox.com/img/logo.svg @@ -1212,4 +1234,4 @@ entries: urls: - stackrox-secured-cluster-services-70.0.0.tgz version: 70.0.0 -generated: "2024-05-21T15:22:55.08391255Z" +generated: "2024-06-06T18:03:16.963379735Z" diff --git a/opensource/stackrox-central-services-400.3.8.tgz b/opensource/stackrox-central-services-400.3.8.tgz new file mode 100644 index 0000000000000000000000000000000000000000..5fb88a13c07e4f558f4d7025972a55e14302e31f GIT binary patch literal 75342 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 Lq8Z$A0MY~i{S{+_ literal 0 HcmV?d00001 diff --git a/rhacs/4.3.8/central-services/.helmignore b/rhacs/4.3.8/central-services/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/rhacs/4.3.8/central-services/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/rhacs/4.3.8/central-services/Chart.yaml b/rhacs/4.3.8/central-services/Chart.yaml new file mode 100644 index 0000000..922645d --- /dev/null +++ b/rhacs/4.3.8/central-services/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 # Can probably be generalized to v1 later. TODO(ROX-5502). +name: stackrox-central-services +icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/Red_Hat-Hat_icon.png +description: Helm Chart for StackRox Central Service +type: application +version: 400.3.8 +appVersion: 4.3.8 diff --git a/rhacs/4.3.8/central-services/README.md b/rhacs/4.3.8/central-services/README.md new file mode 100644 index 0000000..9f1776c --- /dev/null +++ b/rhacs/4.3.8/central-services/README.md @@ -0,0 +1,179 @@ +# StackRox Kubernetes Security Platform - Central Services Helm Chart + +This Helm chart allows you to deploy the central services of the StackRox +Kubernetes Security Platform: StackRox Central and StackRox Scanner. + +If you want to install Red Hat Advanced Cluster Security, refer to +[Installing quickly using Helm charts](https://docs.openshift.com/acs/installing/installing_helm/install-helm-quick.html) +for up to date information. + +## Prerequisites + +To deploy the central services for the StackRox Kubernetes Security platform +using Helm, you must: +- Have at least version 3.1 of the Helm tool installed on your machine + +## Add the Canonical Chart Location as a Helm Repository + +The canonical repository for StackRox Helm charts is https://mirror.openshift.com/pub/rhacs/charts. +To use StackRox Helm charts on your machine, run +```sh +helm repo add stackrox https://mirror.openshift.com/pub/rhacs/charts +``` +This command only needs to be run once on your machine. Whenever you are deploying +or upgrading a chart from a remote repository, it is advisable to run +```sh +helm repo update +``` +beforehand. + +## Deploy Central Services Using Helm + +The basic command for deploying the central services is +```sh +helm install -n stackrox --create-namespace \ + --set central.persistence.none=true \ + stackrox-central-services stackrox/stackrox-central-services +``` +If you have a copy of this chart on your machine, you can also reference the +path to this copy instead of `stackrox/stackrox-central-services` above. + +In case you use image mirroring or otherwise access StackRox container images from non-standard location, +you may also need to provide image pull credentials. +There are several ways to inject the required credentials (if any) into the installation process: + +- **Explicitly specify username and password:** Use this if you are using a registry that supports username/password + authentication. Pass the following arguments to the `helm install` command: + ```sh + --set imagePullSecrets.username= --set imagePullSecrets.password= + ``` +- **Use pre-existing image pull secrets:** If you already have one or several image pull secrets + created in the namespace to which you are deploying, you can reference these in the following + way (we assume that your secrets are called `pull-secret-1` and `pull-secret-2`): + ```sh + --set imagePullSecrets.useExisting="pull-secret-1;pull-secret-2" + ``` +- **Do not use image pull secrets:** If you are pulling your images from quay.io/stackrox-io or a registry in a private + network that does not require authentication, or if the default service account in the namespace + to which you are deploying is already configured with appropriate image pull secrets, you do + not need to specify any additional image pull secrets. + +### Accessing the StackRox Portal After Deployment + +Once you have deployed the StackRox Kubernetes Security Platform Central Services via +`helm install`, you will see an information text on the console that contains any things to +note, or warnings encountered during the installation text. In particular, it instructs you +how to connect to your Central deployment via port-forward (if you have not configured an +exposure method, see below), and the administrator password to use for the initial login. + +### Applying Custom Configuration Options + +This Helm chart has many different configuration options. For simple use cases, these can be +set directly on the `helm install` command line; however, we generally recommend that you +store your configuration in a dedicated file. + +#### Using the `--set` family of command-line flags + +This approach is the quickest way to customize the deployment, but it does not work for +more complex configuration settings. Via the `--set` and `--set-file` flags, which need to be +appended to your `helm install` invocation, you can inject configuration values into the +installation process. Here are some examples: +- **Deploy StackRox in offline mode:** This configures StackRox in a way such that it will not + reach out to any external endpoints. + ```sh + --set env.offlineMode=true + ``` +- **Configure a fixed administrator password:** This sets the password with which you log in to + the StackRox portal as an administrator. If you do not configure a password yourself, one will + be created for you and printed as part of the installation notes. + ```sh + --set central.adminPassword.value=mysupersecretpassword + ``` + +#### Using configuration YAML files and the `-f` command-line flag + +To ensure the best possible upgrade experience, it is recommended that you store all custom +configuration options in two files: `values-public.yaml` and `values-private.yaml`. The former +contains all non-sensitive configuration options (such as whether to run in offline mode), and the +latter contains all sensitive configuration options (such as the administrator password, or +custom TLS certificates). The `values-public.yaml` file can be stored in, for example, your Git +repository, while the `values-private.yaml` file should be stored in a secrets management +system. + +There is a large number of configuration options that cannot all be discussed in minute detail +in this README file. However, the Helm chart contains example configuration files +`values-public.yaml.example` and `values-private.yaml.example`, that list all the available +configuration options, along with documentation. The following is just a brief example of what +can be configured via those files: +- **`values-public.yaml`:** + ```yaml + env: + offlineMode: true # run in offline mode + + central: + # Use custom resource overrides for central + resources: + requests: + cpu: 4 + memory: "8Gi" + limits: + cpu: 8 + memory: "16Gi" + + # Expose central via a LoadBalancer service + exposure: + loadBalancer: + enabled: true + + scanner: + # Run without StackRox Scanner (NOT RECOMMENDED) + disable: true + + customize: + # Apply the important-service=true label for all objects managed by this chart. + labels: + important-service: true + # Set the CLUSTER=important-cluster environment variable for all containers in the + # central deployment: + central: + envVars: + CLUSTER: important-cluster + ``` +- **`values-private.yaml`**: + ```yaml + central: + # Configure a default TLS certificate (public cert + private key) for central + defaultTLS: + cert: | + -----BEGIN CERTIFICATE----- + MII... + -----END CERTIFICATE----- + key: | + -----BEGIN EC PRIVATE KEY----- + MHc... + -----END EC PRIVATE KEY----- + ``` + +After you have created these YAML files, you can inject the configuration options into the +installation process via the `-f` flag, i.e., by appending the following options to the +`helm install` invocation: +```sh +-f values-public.yaml -f values-private.yaml +``` + +### Changing Configuration Options After Deployment + +If you wish to make any changes to the deployment, simply change the configuration options +in your `values-public.yaml` and/or `values-private.yaml` file(s), and inject them into an +`helm upgrade` invocation: +```sh +helm upgrade -n stackrox stackrox-central-services stackrox/stackrox-central-services \ + -f values-public.yaml \ + -f values-private.yaml +``` +Under most circumstances, you will not need to supply the `values-private.yaml` file, unless +you want changes to sensitive configuration options to be applied. + +Of course you can also specify configuration values via the `--set` or `--set-file` command-line +flags. However, these options will be forgotten with the next `helm upgrade` invocation, unless +you supply them again. diff --git a/rhacs/4.3.8/central-services/assets/Red_Hat-Hat_icon.png b/rhacs/4.3.8/central-services/assets/Red_Hat-Hat_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fae985e3b0e5cfbcd1aa58e4a5b9d99f0274d937 GIT binary patch literal 7393 zcmW+*2{@GB_rLGV7-JuMjO^Q&vS*J$k|l;LAsN}r8Yv`W31zFu5^7`@N<u037CLPT2tf5g0`hg=A1x zc$r)nFP4xq&S3xu$o#KB=62F60ElFnpE9z)QMfo2lXlc8rhC;lo~7x|%eK!78Nz$W zGW5d_1;$4FkRFdc3Z+_k`B36zi3NY7hANK&j~xb6Y9TJY&}cVeA+LG5Y*Flmxp1N| zF2Y0sk^X_C^oLDh?Am3%lG^85Psi{)HrF;EuVySyM*r(CY7U#ZY52hOWrMa}L(A{{ z>B#i&+5$jazhLXJ)Tt?X-D7jaQuu>%q<*~m110lES&jIE@b5QN*PIDGl>nU`#CP<* z*TKSLdRuP5kvv@9eAlY+j5^3f1C+7WT_5S9?8fI^yKWX8SXzKwhO)N-Jmd(3ei6hM zn58lF525sGvF~%lKM^t7$hmTLO|ME$IulG>d`jM8r}b<}du)Q9&GqY)o$gI97xqnK3k%g^OQM|}0c{TUtV#@6uZe$1#M75LA+)L08 zAld7N>TA(mek{Bl$gusT5vM{>M-c>G!XG#A_J@D$)bKIW3%yBuSmB2`eDi=g`kC<& zqAdd3I|>aXUv5*Bizhd9w?Db=7O)})Q6(7~QJ9NEE?3rzSJwZj>b$AIp67D+6B-;J zqzB|0x=w~t}AuKD34BQ2|fr-7(xwnBBllMtlPiJ#_rb#0EziJR&ZZ(1 zFF(PZGx-4ENK+B~+fTr^`|Ep^3?RFOg1)ejP-1}8xas)dxCk_ zYIXp!mPF~B3Etby+hK8%aWj!yJa*zn5-T}$O5TNioyxnFJXi9#7#5P}R&Dcx%RO(d zgzcF88Z$)K+`JqYObK|!9Dt_A%xRMdBA?TrT3Q_@{-$78@0({Fp4zAcBHk^retX~a z)Ny<4Q^rA(VA6CuP1Bro`}~<1G(*H|I-A5$P~+!%YmtWLhww@;*+o|#Uw|4&MX%s} zQeg5FATDkW$_(o>xI5bpQPj6Z+B20yNF4M!xj8m*MxvnzF}<I2f=)kL?oyS&K?;PV&=s~9#rq2)E*vmoB;^3oj7apgHy{y&yWT02M{{&Tt@v?j z3Ire3Ew(h@X18N^c(_5IBp|G=?%Js_*gE>3V1s=BpG{JMFtefw|Jg8*QBW+6z=q}R z!+-Wf5f~C2FQyE4<6Aonk~szF3n}d1EbNrr&lI2MtsDy~|gb zWxHlVeo25oJ#=LpJA~tb5pS&@!r!BTj0CuR>K_-5RUqMEBB&J96NbG%Td$1MK@p+` z_u<(IK|~%jIPr}xNVK;HGUDJ*=Y%0nRDr4p$ezCe5^{2o&LO=#nzdP=Ubm0^@h*>DSL(se)s>VwG-k8B&j<4D7+L z@00FCi2(LoF$kx`K%YSaM!zz5qIw6v%p4q^*PTv^hUs@|W33U`$hx-u*t6r~@w?DX z6Q+B-31pd+os5`C8UJ^`F|fUB(Q+Bv8yH@GtWMq7zu$$W!4`u0ZDM4naQH9A*re3A zc7^|{efQo{NGsB3lizf^Y?>GJsq*>;(f$EnNkKd=O zq5;$ByJ?fogCu_QSaG+H7XVJCnxM)J-m}N-+UP3;##p%YGl={!ycGhgn*VOvXz6~r z@&+pmjCjgY^UgD?Na$_tcD+7ao{;YIHDD#O2C!=}Cj8?s-L-!;rMqP#6edvS>G^s! z;P1E8n$(kyN->QWc9Q*E?Of_C3a*mCn`%nV;u@{gX8B&g+2Pw70K^)o^c ziUe}j*<{mq(gKH@f1M=n3(_pUb{mGC89zvAyqT;~^ae#dmIhBNc7X7`Z9k72_|yOS z8q^b+*{l~e5;|-w1h3n%0Ec2WKlY29u!*`yLc4PQ>*~)!pQ(8|?Fe{Sr%NCR7WJx= z$ks}*P_Q3opD;aIB@-l$1+~xb)A9+Rk^TF)tL8FOTy_mWsPulT(E&+Ub za+}k*F^ZuO5j;FS1KOg^RxCQ4u#CFC(Ugw20`g83ygj)$$`eM~&=huhM9J(8t-BPh zUziB>6UxGef~7$YyE=spp0ELPL3KgM>aGGlaU4d(m?pQ_dI|XGPq^~UPm_N$&Aq2E zTQ)L)yrsbDN_`N}*)BgP@dX*a7WK3XqI*0*KnMPY%+`R4-`!P9>h-My30_j2rrqfEc(V3( z=j)n!1u*ejEc{1s-r}R{-Ufe=Lo(|HG)Es6$YhXX*tZkBcs3iquqNi!-l$9OwAS|Z zWhuhH1uCd1Y|LpSp-A^c!5j38X#FGMCuPs(zj<>^1pawHczKe$G))BlBDFQ|_jER65>>-dsuF!WjT#Gm|guWW;*dg)b$;KuI2?}4LZB0+Y)7Y4J~d8Aa1p&E7+ z37z=^WZZIY#FnOjN{W#5t+z*|%Uw~BI5-9)5(lC$GL_~VT^c&R-X}1{s{$ar8wZFc zTPhCxt)j`HlKhr1Qz z+Q>b-!vfoyWxiq-b>US(C}9JLb6Da@@uD1f4+mXTo+`q9?`>nrvL(mCdo30MJ?q7> z;QQrbC@*UG`~D+p?WVG*N)%mTtszo#_Z8FOcS~STzvW-u_XFC0P*oDn@y=oTA_m@% zG60`B6X#A3N?rkC6=m+M5SK4yLcak9(f69aQg3UoSQQw+43z2R~og%J(ZrBB*>Me7K_&4 zUG|4)0u32t1f-Zcm}uk69Q*v`^8>DHC9`%~cQeNSTYV=E6q?SB9}vUqN3?X1yolvS zS1bLcIcL_D%*eSLm%E%|B5Io>(j#r6v9zZg@#5X4ECk_6nLtBRRE=tTTD#n$hI;Z5 zmD3{zn%@_vw;qR^Oea4OztMy-m75SnAh2gqaaW2Oejv0aLSdw2oaS1*YR$6Y>d~sK zZ92(B6Xh~-BAWuctL}tjX{g8;bBwDf@U}j`o87qALc5ZGGEwqzmeNvIQ|6je+P0%l zQe#GeVUa+eup|)1f4yNdL{9f=8a>Ec@2JIOuVCBV&nUlj9@k$QZm1|L`;uwMOWS*8 zrW<-wE$qEXICO%Z*!YW=X8CUF2Iog&sG1|SIZI0Ap3u3SMUnLOsAxpsr<)inW6% zYeV*i$fPx$E6s%}@ScC8bEOo?c-FdBclk}V(B^GL3O01+F7pFce1BceX?P{#?lz&+ zF#B=rGYwO3w5U4$%Ej`2{?}^{zIODFUdAhhy|*=IqW1|-o}NkmXGK;_N{y-!glU}< zO6+OXf7^op5xjTG<JNG#Y@ZS6pYdrFupbJM$o8 z<%)d4n;43fSlGo^RfWByet+6~i_l^1ivm|~-P3+EcbmdL+@DD1Djk`)v0iqg=F5rj zUePMg9W6t}Yq7_Qg5T9L^%b66o%#CB(zQ2=6Yhu*e5F@~yl`-_HXW+GuCyYf_nw7g zw`~1;MQO?_*ht==qHh7D^!|4D@u(lOBgBwI=i@<55tWxxudS`EoS7*pQ}u)=>xC{% zrbg%jpT!hSkyQu(Z3F*D%Vw`4Hhi!(w{R}ElEdL~bb+Cjf}NB(!CX}l%k zD&(vSGS2MS&8Sl=W3zIWAC!;b+70Hgug{VWd>o~;I>I+@wmsE4FuMFGGv*UAj(5Vm z6ppvqkVrAlgF7&cxUs$)g~>d3u%)z2uk36~*`k$JZFi*q_VY4~_3sOPu1STi#(dwb za;YN#r;HF-u$R?NN&h+Nf&AlJIx_u0sm(2F`x@p z!IF>8>$^~88w;o$KVMgr{)(RExk^*Qu$S9yam;b9`x&3w)B>q_Lf2 zXkh{oWqX+FSipucAy7i!BjTfe_psY@nQtqaRnZOW@l_&CmQGC;1u@S=txRHVNlVGJ zhszc%17rIIHwW?HLk62jr5*ywM9`5qET;H&nET{V&C2|prmJz2fmKYp=D57rHrsKp zZZXdW z&DU+a=fMvW-aURQ3}kL^pk&zu7QC}s` z7C0p{M+NhM(|Mt5dnunx@O}Wt)Y!RC8@4HZsAn9DCZl|&E512l9Q;x2BJeY#=K=-t zxraG@_*dof)L6ZaS-ACFkE`{v!uv51FY<@n5i(i~P1e{~rlp3nLGuwCpY30_F};pt zF?8Ov&60wX)gWAVWPS)iNZOiod+EW&pV9Hun64*MCjZ8kh%{q7!(VV9-={F$2rSUJ zW--1qKx67=M!($sbdu}!<=syU4~6Et7jw$i^4V6tGVGvPR7Iv6eq7!-EICH#??Myf zY_809ek8>lH?;8m1rsuHqEEzRyCOg<9h=9xzh5x;byif!bK-mPhDINk$)8biq$ z$h3TR+%V11$q82s&_AHru!}AS@$2J5iw80ZzU2!(Db0<~=PRb|1xIMOMkQ9N1@?GV#OG zwwAM-nAi7uE{Z$)02TSP`%31DToz8E4|J`hOh;gWd%P74>!H0iXi&yP7*$5;+wrya0Wkhl+0qC&8ANs6ZE{KWk^44VinjE~^?8fw>^#+#dM@{=5)hoZN;g`wV({j{*UK=_zJ4%;{&uojcd6I>FWR6v@s^%P-A0U6WtdFm4{{ zMt@%+2q?&YA#$#xxy)%lL8C9eVN-2nT6In>c<&8|zQM~TfR-RU%3G{Hba2u9fn1{r zRKpJkR|GXfDyS}S#^8kUpM`I_?`%6QMDVdo@4jnXH!FP@U8bmIQAB-W#-h9bn`u}S zNFt~zLv9*!Z};-Td!5bgQ9-I~Zw!vR-H6r82nhf9HsVshLpp+xC&`*D&EN5_6w@Yk zt^aRdRngdqO)0y726MWkNQJC9z#fWaZbiw%6~o9JxbE=B! zBkh^Y-K`R^D#NO*Ta7u8mLKFSWoy0-U2GNCSU4}2@m%!Ck5i0ZvAubrx4q|Xi=8P@ zvM6ZtX4aS>o%YDxUo)8Nm?-OQmz^SG+OlRCH=yF%9fd3)w2~e6m)HN}WGzdIU}^4? z+@PD|nt8rQi>e=K{5`i>d+T}l6sA=1d2WQSflwXEM}%Ajs8J}&)mG^j7tQlxZ<#Vq zVR2gKFK_>~W{W(fH%>15*XDeyV%@Jy_8GQYlkOZBboupXCZwMU8~+LhaCe@;-#uJH zx+G3@?p$m;1i0$_pUPpHps}rJy{P6ZGl6#DC_F?L470`Q6rA@}6NEtIqPfBJ_W#Ts zg>XBc6s{1)4elkoL&S@y3on1bo=`3zz|WbpK$@{1F3=X!*Z@}bD-&Z~zrgqAZ8JhC z^7&SFPKFJRHLoCRz>0N?nTiLh|2*jl7uq?56qA@Kkw8^jgw|Htj(L@RqM!LW3fqkt5l zEKv=CdjeU$)E&ThR7U_v6aXv?;(0FMYlC>^!icG@B*MOe-}x}qX}OG&pBEFV0j&}V z5VMc=hvGSao1SKf-aO+QuNsqT#Eg}E6+}PsECp&DHQxD*BJj1;PqIg|LVi_m)&rUJ zP_6fa`0`_JXQ-cHC(1bLhPED$QM3mpj1BbJ5niYTh#WIJ%W>eyJ5HX0pyIcM21s&P zJ|MEmGk@j;E2CenMbz2+?0gonjB`uH6-DsP*}=qegRJ@~V_B5-_SOa*)gLe;g&_Z2 z*dlwhq@=AvKuJ$$_KGJvQ96wagbWL{P){VV5~ZtF`%1#b4bb2$_IK8hSOWg8bN%BwMd|GNPjxy(CCbR|`8F zssxwuZBRrv^h)AjF15+j{y8;aGPpmAu+k+sYB*4Ao_#c^$ zWRPWaRjq$0D*!E9ZjeX)5P7)IxZE9f;x5D=g$Sxgg_;?V1hMnZ?0ELIB5i|vzm2$o zXuVMgHG->tPK1y+CzB`CyliL$Zd7AT%Tqt>jfw3v03z2!7$r;s==(Mo8&C+U=$dm8 z6csHPQD%WsETzeQL=JR>oTkO;!`uBCNd*;afbe{J>rewmd>`=dUKQ&S=e{#I9$ul7 zQvD&28$iTplwVP_Ua0;`;j})AKpq`4k!9b!eQ*re#JuF~G0BXiBmk5>BefEM7AaK# zt*WbOPmCChWytg@R?z%#d@B`TAJwvQsyhPhiuG=H1W2m)WMa-YLTJ=A8XVq2fYUG4 zQywTue&z=o3f@fvDhSYhT96xuY4|XYAB;S}NB|Ya>N(o@5Q;`aztkr5M3xv?osofu z04q`Dd@4;4ygwO$IlQyE`H_L;Z|6bQ9Kqgt$g#<30*E|S?|yXFD1+10wY?Q$5aCl< z2VMLj6q4@AQ0n-wlmx&jcC!;sq`%#$;0AtH3hbOOWB=(_ozab?y=9rb=*2w1Qio zD*^(`rPT>=cIi%|eyu$g82H-YD<(GrUE!qi4fVv*l9L!SNOZ89GG#^~hRKvasx8+< zm%CP<26Ghx>@#juWlDZeaQW4KlEyPRWf(B3kGm&of=}Y^e&xk58Pl805&+%WX7o$Q zM@Yi^z2?rvjm6AV0Cq}A={|Ocy$ZiVq=R?DinJdGuDS67@{xt42=zqcD}5EhF~0=@ z9Bu<3>t*6$qk!I2`LMvDo}wq%;d&sC064W4C5fY)(MO#8vgdl-&z#t*o$r0Z2Z7-( zPR(U=2e#;03k5e)z1Cq1HAhI#K^y?)(Q2cnOJ~ZfgGwy@<<)U5ewgj|_MXd&g?qAS zKw!3m?juZicrN=3X3dqfdtv^W?hcgSZ|9?l2accs(KJA7NHf~ZTq`SSujMi-vsA*y p^-Rn$|54K)7Y$(m7)#F`LRCY}u96!lM@G&Pn44Oksx!vN{~wo`Q-A;f literal 0 HcmV?d00001 diff --git a/rhacs/4.3.8/central-services/assets/StackRox_icon.png b/rhacs/4.3.8/central-services/assets/StackRox_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3c136e3990a7382e8742c9079028abe00697c82c GIT binary patch literal 13406 zcmcJ0WmFtZx9$w??(PI91a}V-T!IYl4uiY9Yk=SuT!Kq*cL)~TU4#3b_dDN_b=JE7 z?wz%Ix_j3y>*}h#>v?uZDl2|QMIu51005}6GLov0^YA|h0uf(`Kj9?-66ecpN3IKo?9RLsz0suTgL;;5YfGaxyaBK(w@TUU+_>Ng^DuR#%L`NBI zX8-^h`=0{{$jl-D0HBbq)U{l+6u$7AIM}fonK~Gov3l4!LbL$@K@Wb&rJb3J5rv1H zt-Uk9hY;1jH25Lc|A^VBDE_75Vk1PQrJzh9;Q%(H;9})uWv3EGqM)D<1e==kt4d1$ zJ3Hh~h|1E%#gU(l&E4Id)%_Ez1K5J?BOf0h8#@OZ2L}s8gT>j?-o?m+#on3vKMMKJ zawN^1O~6);E>;fq6#tZKWbEMTB1A>?PeuRr`;T_ISegHKP4>?J?iQqjZ2zRNePm^4 z`>(PgSq1-*@~fITJJ`DZQ@n<~m5VTk;J=jrxA?zn`;S}_4t9=UGiPT=HsO!|&hkHH z|65-PY-I-N-#^v-m;V2h{cn9`O9vMR$g>7pnaJ9^n1Lac{X6%6Ht_$h@$a$(+5UN4 z|Ksuf$JqQ!3K<+>Btf?S8fal8bScJU0N~>w8s_U9GWue3P0 zQj!?Ouwi&GN9RrL16nq9CTBW}ZhGE}=jV9sxX>`r%Ay!=2kQdY9$&5u!)CpO9bU)L zJ~^DX-+L?NI;(u7mQEFoPykZHF-xOp#SqjId^GMh?hhD<07hf}zZ90wsH>~rY)N23 z<5Ay=A4BhG#W2FEPW}EwCg{@}Fd$=>Fgon>%XWT0EUgY9<3h+0YW-1?fB;(4Ozimf z`zhB+lZ_Ujh$K^Yi0UjLZ>i`WHuS~>(&ACnvePVg-KKM!vpGV_b}u^2DpD*WZOP__ zSc&12g>3j-gx|*9s`N!*=WDl9VcU~G*c7)4CyplJFr;ILa3zVE<|@*6hzNgbw61xe z@d|%N2Fv)pJwt~pd4`~f%7o~I0lv-FbtlYnM9zPMP=-u-)ra|0s;#HHI8$rDGCk_5Uk~+5AM5-hdti`LRpG-LpRS)3}Fnj=I zPe>F4dTnRM%GaBBz}NN8iPyurfdCDA8NGHV_oZ}g1U{-=)S#MH*UB(e!K;ikOd}n9 zR=xMbVoGSuj0DCfiom&SZ}cGr{fGo6aZ(@^i|vl6Ggbs+PUfDV%^TxjT{=1NckpMW zl1UJfhxqV>D9(>~O58FA0@c-G6GFWq_VLkQ&)+Mv;)!)pw9G`0kLqvuq8IYsA1QZd zXSpZ4S#yxMCZhBuL*03O@BR+4pc2;Nh%=r^?QfeAE7vPeM?r>;KvgC~+NvyoQPfmk zg+!d}w>cYAvI*{01n|TpU~cTIgJ$*X0sL>vkW*LY+TS24R$A#)2E0(aY^+2#fOrmJ zMh&i!JolfH1*2$S#T=u#*+Jz-!`O5kwzylSdE!3tN7#t8*A8=YfoZP$5?pV74*E@Jx_ zijJ?1IdIznDF6nO@Q^k;YCz?_{aTalO78VtHZysWafZ!;U4;orWP*VBEgp;B=QB09 z%H^%h0=59>(?9;>T(#tGdBh<^$)+%vo*6 z)tjkxyaLH_4h3q3Y=PG$x?XD2?sj+2#%Qa2B|=qL*wD{$*{BhOQIzw7OG_W?A~j-; zgW`j*D!b^?@{0L<%t=~(ZqvrU)wCKMTv85jG+*$Wu3^@HF?1NDi9uyfZtG;#YgK8l zl)14IM_Ra>`!hD9C%u*arBGCBphWZIEz@phlIm2TeB;k(2P14`OHuwFX0KJbFnjq?cZrQ`5~<8Df0P`?W4X) zL2$Ai5iC>@U?ZxCy|unCCYWaq^cKEAtT9q9g+=DXi9#anLBQ=It|P z6iu|(yU}roRhODR6cbFPlizX=PX;~d=yO~~>mm?uZUCHASXq=x4pi~LS zfStnjv*LqwMhn zCROx!x&~xHck{0rI(9c&J2J2FbU8c zLtBHq@HcmQtmvv>xa+_3-*Ii;q^qbzB^K)NlV@&ciKFc^hOxB{iXn< zZnB%&eyjM->)c<4xAg~XDMO~~U2MEAH!({6hA|GW7$%-Zok#>oUfgvw$1$%DT{Ke~ z+e7#c_2L~9;@ja{mR`ve#O}(RYc}Gz80A|D+vW#9TSVtDea|F(7p!HaDP#}Tw_5`H zGdP@&3WugrB#;*V_8&zj>iPAkYVkxY%vJCbh`Ko+553RA=QvGA94*?fs%*NjL~`c{ z<%$=?-pMcpgoGK3#!&|=>rRnr|CtBDsyhb`D2&GH-iO6y%J%x`8xr#u3pn+xJ;%#YiO(kVz9YY9w>vhqfsm+^u=~ z`7qeW8aTTyeYL+M;l-?kxuI5=#`t#Ew>FH;msNhwNTHsr0^2r_9(gUBUQXpiIf zz2i9OQ|630;kiJ4+vBN}e}(@{yd}mdHx&ugoCH+}K?bP^rvJCo^__3!RUTTEq!Y`S zwsR$DyTR!Tz!4z%gqkh)=~HU>V}My40Z+JOT%Z|UX$~Q<4%EmkWHb0xCT*Kf)SGKMAMp!5j&g2t`Bz2ToU>E9 zQXe^t_JMHM>h@Bc$0P05EJj5P$5cKnzkYiTb$p=JK zA)gl)r0PC6>X~e5;?!}(yoq$lN?_&u2UHc*M6Y6AJkNuXdY2;dg=rFjH1#B2xY%&_ zDzBs6Qe_DgTJi`-=XZQie|v`7OYpjT8R!`BFUS?UaI!bTUKv%KA4hoL4^1htqG3B-_YBi_>Zsq@iLYN=; zf!P~o4ElyTEujsZER6~6B9Mnig;0{Z%-Syu8@T{AiiR`ra2f$6?td); zCwVKyY<^4{G^4=}s;zH2`I78o_bfI;oR{ot#Yde^zvM>qHExB~SUr&1#&pLv+D#G? zd;5d=Qv5~4O)nnXiYRhssuXcOI3Oc%9W_QFI-tVeT!10&oj z7wdm)5d_5;?+3HF#E9 z6WvsUamdv;q1q1&n@-1{Cf7viUsXp@r(I)CcVKlMIH$vuhwAaG86ESY4Z6lARyt2G z?6O}|Rnm2k@_>n#CsqA^J~d_aX+l0X>aFA=Y;6AbZzlF)uMoSWQ}#(LSVjU<(4@i2n&IgyQfn3>F^kN2M@RMc5 zn~0`u(){l-=(SI_7;!a6a6LICBixKl9kcb6A2a+tgJF4W$4_l|&KcuL`o7aE8N?iM zN8#auXQWxU#G>?<_f@p|p2sh?c79}GAMC*6*(ZmS=$b?;3Fgl|gJ1Xc>`@Q9?#Tq< z>SkB@HOD~HA>5&VZ1GOXI0C#PAD|GFqi1436Ci%BMpX%pAl~u&U^ezHVTlreb?WE1 zz)6FSd`HG`B{=%Z@& z8r_Vv#Z3k}>UEjQ<;bs0?V$qlS1j+?VzjMt^(~e8>vH#tza63kM=)~0P;Lec&)cF& ziB8Vd)&qo7K`j|drhFqtR?-~)3Uvz2?X~XCx`iTHg8>)=Y$Bpr)G*3Wx)@%+V{x(k z7k2Wl(gaCjy?L#07G#B!$aR=Tj5*RoIFiqsz( zZct1K@}+!6#pxRIrCipyF}(_4mIWi$L#|^Roz9`m4O@LoUQk@H_Uo@uh$CJfIv{m4 z1qIK&hL`R9V5KAa)q5wsrYtvBUu$tir*v2T(J;RI5GA8sqWgDF z%12ScASSy7z{##N!E7mBhr|}t$j0g`gZLug{Kj}p%=C@3zXQpG(b@sB&wajfzD{W` zQOy<16}Etls*n+&U^e1yh8JcubaM04+D5pkC!e57I$4=xkA3M- zz!4di`gYu37TrBw`jgF6yo^VF^p<(yvf6NiAfgD&*I4)EaoPP(`GlEtT<#CE@poUA za$?aaBokDbbfx-C)^W2)1JouL4GtFd)YIds+m*oR23I-tIS{OQAQ4CV9cgM(n8Q!- zvgb{y2?5+D_O2Iq{A^>C*e#T$6S4u({{G&x6slNka5oipWu@d!`|DJEm>CihQt@*5 zEIuKd0h{hGST1zv%~^iiX>fUt{0IpetlIIzkld+1LpdWCvIb#!#9}wG8~b=;nrbe_ zQ?q+bPqOLSUOFlTy%tL>m|&#4N%XR5zBg*LIK(`Ol>Pi^GKJZC{;~UY8CBpo zBe>GVQqmercBV2@PYpLUtgh55;p>tpV`s%6x1%%x2sO`%?T}9Z@YhgkyW%^z1;Za28h=QW<&=@n# z14J?59+F+#z>Y(mb?+Wbvv)Y@=K&rLhQCyyp;zk56gmR!Kx$mB+3M|?QbqaLwJ-4@ zCNqEFS>WeUZH)<8*zs}d&!qzc>tsE*@t$eF*g%#5PKk<6_HewO(w&0h6SHE<+t|Q> z-yeP)b+$DeO^)?C+MD5TyiLdev%7JK(v{(J*Iy7*9|k$zr+8J9vj{02Juh1)W1(LQ!}lYn zTv-E;2F4ca-oEDCXHe4{dPV)Gj<5p zq+AgJc7pZds*5T!Au!)sI8)GUO5t4f-h_!8L74nnqPTdahCdeOu9$=OJQxz3!yG?0 zKFf7_V_&iGCc!e1$$)Bv*l9&-KikQaPNWe~H9B7>!{HtN_o>AbDfVz_;$s|mEq-Pu6&$>HL+Z=eq0~Qn zpXkiiblu5PAQOFKzYXq2%8L?81z9{SV{23XrKcajK87Op%PSxOYJuVFum_T_x4Iqx6}o0H&VyzVQ6dO4zuo5?1W|R?%~>4k`ag(D7?o7O zO}IStd>b3z?ZZ(w2|2CZXp}C$?Cxk3>#@Xr6J#k=EzW-myk+HKqwxALi)wF;TgY(| z$4QlCK9JevIa`~)kKcbw5bXCCJH2LAG)Z&Ry$zf!r)dAz+6bE-RD!Y6yTg6dLZ2FH zw734+RVDtt^yMMdMa8ZC`!^9)8_BIvkpVK&c?;lIX-?F?XypCzXgPUhQ{ol)13gsXW)(bRa(%7Q??q`P(y=gj49M5V-#8n&wL=B@=IcWF zEA3fi&0x-)hYnDca!M$(H|f%5bb|Dha|y#TzPYu5JL|$U9}ud;f=F9=Kh=9WhHt*T z=uq%?K=2Ny_{>Zqp8jC?0a0r9)Nf^)0xwz@$Vi3lapI^i8u1P?jMO0WaXl3;yvyjK zkM)2asFfMc1kN~qzrR7u-!nLO&`*i6PkX1?3wx-BobhYqMl@?VCAPz<&jKCmSt=EAd8tSpeF#DST~?g|Ez%bU zF(V_NDe%Lf+<0Hxwho1#$AQ!!6KXU;EhlUmuEwiW))cA3dZz*5mkL$v*C;QP^Z?<$ zSgg65@fWx0bpARLL&s`rw@Lno&@{>gnr<2JB~`|!Sbynpm1dX+EMsrqxlF2)3dhVbI!8a1sENT) zs4M|U1!vMSaWl$=^!|`SsM_jRTtxm>JthZSE^jTaQf6f;g9R53>0S=FC{7BHaL=Qc ziRMNyGA7ZHB|~7yQavI~ug9-lMGXDCQ5t%`dyDB<#Fyc3COnzWPS@kG^J@{X_Ze^n z^nOffvz`PMbbj1o{UBSxGZgAy$;6_2W#@0u1bn0E;Ao0UCOw2pj_D|EI@I!rYChwq z`4~4>+gDoueENvPuzo4X0!c|&3-htfsvfr+SB^pUGVcG}S8&=H1CQbJ9Vb0%^3xdN=(I@n7=n>@P z7bjWFx|ovQ418C#n3`D;_~c<9X&KD?`*Js-|4F&nf8wq?yIjkjM0d|qPXYG6;G z3b$2{U)c#kwXHL($!qnyCfl;W*UPa2Uu!D1f}TNb;NV;}QAEx?i2d!wV_sYX#I?d` zsfxc0R(W6kKtf@Ae|_Gb^^Jo-eAViQn$}&0$JL-;QYX<-X3JrVbcPz%gMPPUbF3~2 zT+ZsLaAoDtc=rUyw5_G(OI0`n{PSMTM3Rl|v6zKQ8UJv8hX2X>{X@_Fn+p7w@QF8q z>^Qk0JU-XF)29%r`MJBR#a$TZD&EAb zJ1Iw?tZZb;UkQCx^>2m_B`{hxZ5zGhBSHqVPWk?>-XGH801a`_gtFJ**lW1rWO{pn z|7=QnbyxpA0V-R`lz!*MW+W#VWbHJcBU>qL*yws5lh8-b#GQJAc_{34%YU*SJk)(j zCg?@wEhOigmiQReg(yPgK{>A+YO!^;0!qJ`T9Krj%P9i2QJ5;RW~v_r-SqhxbS4_O zf!YJ+m+Pt*#FuaFK?fGLXr#A>+TzwInHzRsaASBr6+M@9%P z^U~$9y+Yc#_133;&U}8F)x7AiPMRu+PI++W_X~pqO@TyPnNPvlnz^>=491Yp*MbCM z28vQ`nxR&nP4>*sGwU4{y7JXJ?U2VigQcD)51Gi9vKSWa{b78NHB$7phV<+0iN!Tb zCbN|*9GCZXSQGJBV+HOXZy_kZQmhH4VJp!2$zn)Ms$AQXzcV`r0eaf)?y!wU&*y!O*;e^T^%WJ14t+jcjWPBIGt>eH z*;JyJKa{LX4%^v>^qy&{i+1)mo?oBu$r)-vk1RVyceo1GYsxqHHiR_|Tl@JFgDAS$2IXqaK>7Yn`pwWJ`fW^2VxJb zy^bdgOCY<#;HL<#9ZZ|qAo`4fUjTiz>@JBwD&!ZYqk5zJV@faXOc;)mJVX+qQEWJ1 zwTFOG08Czk>;I;|Kmz+wCu4PZ$WLQy~m#3_9b_khSGgCm*LY*-;ysb6?hZWc1$qM`tn)C94-Uy+hJ3HL!gOAfO5`$?A>iZ5 zX(&#}xIz||tow%{gQSD?4&QePt1Vjm3-)b$Xu5(6AKj(?tCi&5ldz(%n5)=y=etM9 zs|v$g6L$e7ORuq&+i+;P+}>M6OC{`>D%t)(b;3Ubl%@^oH=ap}6x;az)f<7pB7Bs= zuM%TRl!bn}4@3MdBmGD6S+7rqK8Eie&;Cv1n@it8hE6Sf;8SM7mR4k+?$jKn5>cGC zX=md-tPfb-NG|AP6twV1DNuz(Ayp)p)_5@8VD$4`LD#D!-0z!-pWpb0 zRvVe5b&)+dPqeSUUK1xfI@ehq@q0*{JU{Fgz<7DFh3g@40BBF`e7_UqM)auvDsy}v zj&f$^Kb&|!l^DipL}|P|40}66C2k(-j_j7o6;xo_Wnh|R(gVHx-8;FtiHV6BzquJd zf2Hp}eg2H*^~B6VeQov>9fMDpVRgg?c9vJ?p`t_K8aH_Zb!C%n4`bE_z8V&ABYt#+ z!?~YdGkuV- zIwCYcgbvTZ?a9_~r@=>YrFj-AH6ov_TyB)zd(ns@6kFPo_ML@~A@ zG83dfl_|}(u*m_V1yoZh250&adB7!4$so00pD!Wb2e^=ER36bn0$nL;q;|pmofQr~ zTdsz-NxRJ2M|zOq^a^mOcl$W`=6iH>^3vnn<$X4|M*gJ$v8y?6G*W$o&4WZCT1x`c z(fzrL`+WCma~s(ABUy|e*r&NBRAIdw!)y7#itiy^BbGef{6?TL5rk^Hli-K2U~DMPh*mYuCQWP84w)Vi*tdRSaDxyj>Y!8 z0}QZwj#AbBydF^+E7!ay7Zw|C$IZ*P`e66#v(N*W1ptoG4&OgBzB$7(_%*pbMYe`p zgjs_8$K3RWoU%a3u8+v9Q7rvuf^Abd%)8%sm1nUA)c zHa|~x|GM&H^;UQD9@bi)X?AiITIR-o@4$H7h3{(jzEB}7+Fm4X3eYr!XVf$K?lE0_ zF7gGI_SQcvKd#gF=TGOT`I$^zp|TNG6hPSRhuc3-6YXD?-2;y>Tu;L|UsbNzuL3_6 z!?R#$-6YRyx`@;Bq;Bp>GQ zd%Knx%6CS&FGCbK>ip*(M+HBHE@nr)?e+b_^WKO`5-&INtS}YoM9+hviIJle#972e z+htOD0)L7iNt3_LJiS3kGR+&8Li+I`tVi7q2!PObqX4H5`@9SBeUGD5%3lxHRS}?9 zyq~i6*sIPQZS?PRg6T&7{DFj#t#O}8(GjruS1$2-y>v|a4t;hZ+9Kzh7BMyy-K8)Y z>Ssgg)8Tg+O>kuPsu&nMjB^+A+%LF{+zBuUK#dG~Q3lug*IkFtYOzsr!FHMUN6(SA2C?=5>V%Ei*X` z0M!LDu-x=$Ax4tlg{lx(B0vB?=%MAdojfAyja2tEMa&-uZ`=;F%#25`$8_EcDHw(` z?%k$Y9L{BFX3Q!cw-~e1rF>U=5fN&mXh-4J>5@&g*wE2x-v6+M!|Wc@hZ$r8KY0u6eGFwBL<*112h!^OP(Qr|25euyI zUCjRr6%F=F5Rlt*-Q(GyBqyl$e>n_g(lShlV@@@e+gV2H{B=(&IvM++Mr`P(199nN&S zgr$8HwlZmlSOl;t5wuh_DSOhYT;UT= z-I64{qZt9rUhkEaS#D%Pna$CGxmxW;;kGy=!W4f`BX5Fq`CPVhUkXDMjOpCZKR zopX1^tv+GDUqJk++NyHGY4<~%2LpEQvc#oX)enO@ zoYZViaS^J;cqwR_ykp?T&mO!;A$N*~x!BM{tq#^ps!tdZ8;|lR2dYa%LPlgxeuoQwZGXrPuO5iROfAyCpZsLo<`7 zjk~2|@}77)o2#P#=0D5OO|M2Em82Z}%#!nW(kww0-b!+tox#wFNJ8>QqD)_xO1npE z`G;5BZQc8Ts`%9Van%Bh8^rqr;Ig^lN_!5UyHw&jOQXi_AX2MT_Fv*bye-{3c(m-K zTXRGp9=`gKkOxQg{A2vRjFY}ZSuL=RoRm0S5^j)2<=t)zKC~WHYo;NBR!U7cN#a-@ z4b}IRZe_6kM~N&<_YKO-acLwHHgfzQsFR*;wf%BbEy#Y$qQ7^V)@WGbrVrLgr7Z9Ynh$-?pAi6tQZAZwps^Ioa zeifB=oSfX!(#{ee-W&#%Yt#)PoQM2}aA6>t6lFHL;L%iHTHjkRee~X*(YFk4YCd1I z78!VB-e|?FHZ9OoI)%qF>uZu#>JoD#2L+Ej)w{1)E@iUHr*x)8LT62xVgQgfw#2QJ z*q7uDM-T2=#MLi@@k^jpg_m$K>QyE`q2D~p6 zT|*u0-viLXH7f8Z z4beLfNUJ7%4RgUDD9Com>d6lGF~7#yOUgl<4Kdn`;~w@IY_Scqw{+CFZh9( zZHp;`yeBb{X2kbN-i}yj3uW#pgAT8Q^H(MY9v<62sFo54JuVJ^+VJzB%b|yoA6UiG z4{Q4|14JO}_D#k{>8>XPwhx$D?{p^L-63ITyXiY_h9%r0f&}s@R8S?+{+_KO?r2Tf zWs@PzW8BhpTOtn0D*Y6i%TepQXrvl*+~|2Cyw?pi09vHW>5td55>;bVfy%|XaRtN~ zy&NtMwvIvgJf*Bo1U2951-*1P6sKRxN!&X#O}>jmWmBHw31J8hn^}b69&^k$h$l(uUWbv$mgqZIg7I+3 zczu#~e`=2n(jJ{ahO!ZP%5eArkwwm|9)L1TskKm+f`FyZ~^&~XKV)eLds9g|P4e+!<>XJiBrUJ3GSNDqjX zE)ZnHc0-UaSrYJB-+a65u_NCO!iivyqOl;5d9BGkX8CLhs4JP%oEwz)^8?rvdad)> z@w}G{I3v->VyyfN&@vxyNByf8ZX&%s2yW~_1PS^(yYEPM;wQHYk?LVj#$mZ{O zv2U27Pz6PN>+Gx6suGl!p@w2kC%~Em1PL#Jq0DBJ?ZG3spBVOWg#@A1UH~LKi~y*VRF-a>G22J)2+V$(X~T0mdFs8c-Th-J7AkXJGJPtJdiM9-g^`m%!C* t_V2G6APDDwe(C^$J^%j;tx;Y@XgXYCubMwn{qq%%tdyc;wYXu>{{cr9X{P`H literal 0 HcmV?d00001 diff --git a/rhacs/4.3.8/central-services/config-templates/scanner/config.yaml.tpl b/rhacs/4.3.8/central-services/config-templates/scanner/config.yaml.tpl new file mode 100644 index 0000000..5efc0b9 --- /dev/null +++ b/rhacs/4.3.8/central-services/config-templates/scanner/config.yaml.tpl @@ -0,0 +1,48 @@ +{{- /* + This is the configuration file template for Scanner. + Except for in extremely rare circumstances, you DO NOT need to modify this file. + All config options that are possibly dynamic are templated out and can be modified + via `--set`/values-files specified via `-f`. + */ -}} + +# Configuration file for scanner. + +scanner: + centralEndpoint: https://central.{{ .Release.Namespace }}.svc + sensorEndpoint: https://sensor.{{ .Release.Namespace }}.svc + database: + # Database driver + type: pgsql + options: + # PostgreSQL Connection string + # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING + source: host=scanner-db.{{ .Release.Namespace }}.svc port=5432 user=postgres sslmode={{- if eq .Release.Namespace "stackrox" }}verify-full{{- else }}verify-ca{{- end }} statement_timeout=60000 + + # Number of elements kept in the cache + # Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database. + cachesize: 16384 + + api: + httpsPort: 8080 + grpcPort: 8443 + + updater: + # Frequency with which the scanner will poll for vulnerability updates. + interval: 5m + + logLevel: {{ ._rox.scanner.logLevel }} + + # The scanner intentionally avoids extracting or analyzing any files + # larger than the following default sizes to prevent DoS attacks. + # Leave these commented to use a reasonable default. + + # The max size of files in images that are extracted. + # Increasing this number increases memory pressure. + # maxExtractableFileSizeMB: 200 + # The max size of ELF executable files that are analyzed. + # Increasing this number may increase disk pressure. + # maxELFExecutableFileSizeMB: 800 + # The max size of image file reader buffer. Image file data beyond this limit are overflowed to temporary files on disk. + # maxImageFileReaderBufferSizeMB: 100 + + exposeMonitoring: false diff --git a/rhacs/4.3.8/central-services/config/central/config.yaml.default b/rhacs/4.3.8/central-services/config/central/config.yaml.default new file mode 100644 index 0000000..d85c852 --- /dev/null +++ b/rhacs/4.3.8/central-services/config/central/config.yaml.default @@ -0,0 +1,7 @@ +maintenance: + safeMode: false # When set to true, Central will sleep forever on the next restart + compaction: + enabled: true + bucketFillFraction: .5 # This controls how densely to compact the buckets. Usually not advised to modify + freeFractionThreshold: 0.75 # This is the threshold for free bytes / total bytes after which compaction will occur + forceRollbackVersion: none # This is the config and target rollback version after upgrade complete. diff --git a/rhacs/4.3.8/central-services/config/central/endpoints.yaml.default b/rhacs/4.3.8/central-services/config/central/endpoints.yaml.default new file mode 100644 index 0000000..25549d6 --- /dev/null +++ b/rhacs/4.3.8/central-services/config/central/endpoints.yaml.default @@ -0,0 +1,31 @@ +# Sample endpoints.yaml configuration for StackRox Central. +# +# # CAREFUL: If the following line is uncommented, do not expose the default endpoint on port 8443 by default. +# # This will break normal operation. +# disableDefault: true # if true, don't serve on :8443 +# endpoints: +# # Serve plaintext HTTP only on port 8080 +# - listen: ":8080" +# # Backend protocols, possible values are 'http' and 'grpc'. If unset or empty, assume both. +# protocols: +# - http +# tls: +# # Disable TLS. If this is not specified, assume TLS is enabled. +# disable: true +# # Serve HTTP and gRPC for sensors only on port 8444 +# - listen: ":8444" +# tls: +# # Which TLS certificates to serve, possible values are 'service' (StackRox-generated service certificates) +# # and 'default' (user-configured default TLS certificate). If unset or empty, assume both. +# serverCerts: +# - default +# - service +# # Client authentication settings. +# clientAuth: +# # Enforce TLS client authentication. If unset, do not enforce, only request certificates +# # opportunistically. +# required: true +# # Which TLS client CAs to serve, possible values are 'service' (CA for StackRox-generated service +# # certificates) and 'user' (CAs for PKI auth providers). If unset or empty, assume both. +# certAuthorities: # if not set, assume ["user", "service"] +# - service diff --git a/rhacs/4.3.8/central-services/config/centraldb/pg_hba.conf.default b/rhacs/4.3.8/central-services/config/centraldb/pg_hba.conf.default new file mode 100644 index 0000000..8229f95 --- /dev/null +++ b/rhacs/4.3.8/central-services/config/centraldb/pg_hba.conf.default @@ -0,0 +1,103 @@ +# PostgreSQL Client Authentication Configuration File +# =================================================== +# +# Refer to the "Client Authentication" section in the PostgreSQL +# documentation for a complete description of this file. A short +# synopsis follows. +# +# This file controls: which hosts are allowed to connect, how clients +# are authenticated, which PostgreSQL user names they can use, which +# databases they can access. Records take one of these forms: +# +# local DATABASE USER METHOD [OPTIONS] +# host DATABASE USER ADDRESS METHOD [OPTIONS] +# hostssl DATABASE USER ADDRESS METHOD [OPTIONS] +# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] +# +# (The uppercase items must be replaced by actual values.) +# +# The first field is the connection type: "local" is a Unix-domain +# socket, "host" is either a plain or SSL-encrypted TCP/IP socket, +# "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a +# plain TCP/IP socket. +# +# DATABASE can be "all", "sameuser", "samerole", "replication", a +# database name, or a comma-separated list thereof. The "all" +# keyword does not match "replication". Access to replication +# must be enabled in a separate record (see example below). +# +# USER can be "all", a user name, a group name prefixed with "+", or a +# comma-separated list thereof. In both the DATABASE and USER fields +# you can also write a file name prefixed with "@" to include names +# from a separate file. +# +# ADDRESS specifies the set of hosts the record matches. It can be a +# host name, or it is made up of an IP address and a CIDR mask that is +# an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that +# specifies the number of significant bits in the mask. A host name +# that starts with a dot (.) matches a suffix of the actual host name. +# Alternatively, you can write an IP address and netmask in separate +# columns to specify the set of hosts. Instead of a CIDR-address, you +# can write "samehost" to match any of the server's own IP addresses, +# or "samenet" to match any address in any subnet that the server is +# directly connected to. +# +# METHOD can be "trust", "reject", "md5", "password", "scram-sha-256", +# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert". +# Note that "password" sends passwords in clear text; "md5" or +# "scram-sha-256" are preferred since they send encrypted passwords. +# +# OPTIONS are a set of options for the authentication in the format +# NAME=VALUE. The available options depend on the different +# authentication methods -- refer to the "Client Authentication" +# section in the documentation for a list of which options are +# available for which authentication methods. +# +# Database and user names containing spaces, commas, quotes and other +# special characters must be quoted. Quoting one of the keywords +# "all", "sameuser", "samerole" or "replication" makes the name lose +# its special character, and just match a database or username with +# that name. +# +# This file is read on server startup and when the server receives a +# SIGHUP signal. If you edit the file on a running system, you have to +# SIGHUP the server for the changes to take effect, run "pg_ctl reload", +# or execute "SELECT pg_reload_conf()". +# +# Put your actual configuration here +# ---------------------------------- +# +# If you want to allow non-local connections, you need to add more +# "host" records. In that case you will also need to make PostgreSQL +# listen on a non-local interface via the listen_addresses +# configuration parameter, or via the -i or -h command line switches. + +# CAUTION: Configuring the system for local "trust" authentication +# allows any local user to connect as any PostgreSQL user, including +# the database superuser. If you do not trust all your local users, +# use another authentication method. + + +# TYPE DATABASE USER ADDRESS METHOD + +# "local" is for Unix domain socket connections only +local all all scram-sha-256 +# IPv4 local connections: +host all all 127.0.0.1/32 scram-sha-256 +# IPv6 local connections: +host all all ::1/128 scram-sha-256 +# Allow replication connections from localhost, by a user with the +# replication privilege. +local replication all trust +host replication all 127.0.0.1/32 trust +host replication all ::1/128 trust + +### STACKROX MODIFIED +# Reject all non ssl connections from IPs +hostnossl all all 0.0.0.0/0 reject +hostnossl all all ::0/0 reject + +# Accept connections from ssl with password +hostssl all all 0.0.0.0/0 scram-sha-256 +hostssl all all ::0/0 scram-sha-256 +### diff --git a/rhacs/4.3.8/central-services/config/centraldb/postgresql.conf.default b/rhacs/4.3.8/central-services/config/centraldb/postgresql.conf.default new file mode 100644 index 0000000..057e7ea --- /dev/null +++ b/rhacs/4.3.8/central-services/config/centraldb/postgresql.conf.default @@ -0,0 +1,29 @@ +hba_file = '/etc/stackrox.d/config/pg_hba.conf' +listen_addresses = '*' +max_connections = 200 +password_encryption = scram-sha-256 + +ssl = on +ssl_ca_file = '/run/secrets/stackrox.io/certs/root.crt' +ssl_cert_file = '/run/secrets/stackrox.io/certs/server.crt' +ssl_key_file = '/run/secrets/stackrox.io/certs/server.key' + +shared_buffers = 2GB +work_mem = 40MB +maintenance_work_mem = 512MB +effective_cache_size = 4GB + +dynamic_shared_memory_type = posix +max_wal_size = 5GB +min_wal_size = 80MB + +log_timezone = 'Etc/UTC' +datestyle = 'iso, mdy' +timezone = 'Etc/UTC' +lc_messages = 'en_US.utf8' +lc_monetary = 'en_US.utf8' # locale for monetary formatting +lc_numeric = 'en_US.utf8' # locale for number formatting +lc_time = 'en_US.utf8' # locale for time formatting + +default_text_search_config = 'pg_catalog.english' +shared_preload_libraries = 'pg_stat_statements' # StackRox customized \ No newline at end of file diff --git a/rhacs/4.3.8/central-services/config/proxy-config.yaml.default b/rhacs/4.3.8/central-services/config/proxy-config.yaml.default new file mode 100644 index 0000000..8692a77 --- /dev/null +++ b/rhacs/4.3.8/central-services/config/proxy-config.yaml.default @@ -0,0 +1,26 @@ +# # NOTE: Both central and scanner should be restarted if this secret is changed. +# # While it is possible that some components will pick up the new proxy configuration +# # without a restart, it cannot be guaranteed that this will apply to every possible +# # integration etc. +# url: http://proxy.name:port +# username: username +# password: password +# # If the following value is set to true, the proxy wil NOT be excluded for the default hosts: +# # - *.stackrox, *.stackrox.svc +# # - localhost, localhost.localdomain, 127.0.0.0/8, ::1 +# # - *.local +# omitDefaultExcludes: false +# excludes: # hostnames (may include * components) for which not to use a proxy, like in-cluster repositories. +# - some.domain +# # The following configuration sections allow specifying a different proxy to be used for HTTP(S) connections. +# # If they are omitted, the above configuration is used for HTTP(S) connections as well as TCP connections. +# # If only the `http` section is given, it will be used for HTTPS connections as well. +# # Note: in most cases, a single, global proxy configuration is sufficient. +# http: +# url: http://http-proxy.name:port +# username: username +# password: password +# https: +# url: http://https-proxy.name:port +# username: username +# password: password diff --git a/rhacs/4.3.8/central-services/internal/bootstrap-defaults.yaml.tpl b/rhacs/4.3.8/central-services/internal/bootstrap-defaults.yaml.tpl new file mode 100644 index 0000000..8f8e559 --- /dev/null +++ b/rhacs/4.3.8/central-services/internal/bootstrap-defaults.yaml.tpl @@ -0,0 +1,16 @@ +# This file contains defaults that need to be merged into our config struct before we can +# execute the "normal" defaulting logic. As a result, none of these values can be overridden +# by defaults specified in defaults.yaml and platforms/*.yaml - that is okay. + +{{- if eq .Release.Name "test-release" }} +{{- include "srox.warn" (list . "You are using a release name that is reserved for tests. In order to allow linting to work, certain checks have been relaxed. If you are deploying to a real environment, we recommend that you choose a different release name.") }} +allowNonstandardNamespace: true +allowNonstandardReleaseName: true +{{- else }} +allowNonstandardNamespace: false +allowNonstandardReleaseName: false +{{- end }} + +meta: + useLookup: true + fileOverrides: {} diff --git a/rhacs/4.3.8/central-services/internal/config-shape.yaml b/rhacs/4.3.8/central-services/internal/config-shape.yaml new file mode 100644 index 0000000..e1ce4b7 --- /dev/null +++ b/rhacs/4.3.8/central-services/internal/config-shape.yaml @@ -0,0 +1,163 @@ +licenseKey: null # string +imagePullSecrets: + username: null # string + password: null # string + allowNone: null # bool + useExisting: null # string | [string] + useFromDefaultServiceAccount: null # bool +image: + registry: null # string +env: + installMethod: null # string + openshift: null # bool + istio: null # bool + platform: null # string + offlineMode: null # bool + proxyConfig: null # string | dict +ca: + cert: null # string + key: null # string + generate: null # bool +additionalCAs: null # string | [string] | dict +central: + telemetry: + enabled: null # bool + storage: + endpoint: null # string + key: null # string + config: null # string | dict + dbConfig: null # string | dict + endpointsConfig: null # string | dict + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + exposeMonitoring: null # bool + jwtSigner: + key: null # string + generate: null # bool + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + defaultTLS: + cert: null # string + key: null # string + reference: null # string + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + adminPassword: + value: null # string + generate: null # bool + htpasswd: null # string + resources: null # string | dict + persistence: + hostPath: null # string + persistentVolumeClaim: + claimName: null # string + createClaim: null # bool + storageClass: null # string + size: null # int | string + volume: + volumeSpec: null # dict + none: null # bool + exposure: + loadBalancer: + enabled: null # bool + port: null # int + ip: null # string + nodePort: + enabled: null # bool + port: null # int + route: + enabled: null # bool + host: null # string + declarativeConfiguration: + mounts: + configMaps: null # [string] + secrets: null # [string] + extraMounts: null # [dict] + db: + nodeSelector: null # string | dict + tolerations: null # [dict] + source: + connectionString: null # string + minConns: null # int + maxConns: null # int + statementTimeoutMs: null #int + configOverride: null # string + password: + value: null # string + generate: null # bool + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + resources: null # string | dict + persistence: + hostPath: null # string + persistentVolumeClaim: + claimName: null # string + createClaim: null # bool + storageClass: null # string + size: null # int | string + volume: + volumeSpec: null # dict + none: null # bool + extraMounts: null # [dict] +customize: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + central: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + db: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner-db: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + other: {} # dict +allowNonstandardNamespace: null # bool +allowNonstandardReleaseName: null # bool +enableOpenShiftMonitoring: null # bool +monitoring: + openshift: + enabled: null # bool +meta: + useLookup: null # bool + fileOverrides: {} # dict + apiServer: + version: null # string + overrideAPIResources: null # [string] + extraAPIResources: null # [string] + noCreateStorageClass: null # bool +globalPrefix: null # string +system: + createSCCs: null # bool + enablePodSecurityPolicies: null # bool diff --git a/rhacs/4.3.8/central-services/internal/defaults.yaml b/rhacs/4.3.8/central-services/internal/defaults.yaml new file mode 100644 index 0000000..dc32ab1 --- /dev/null +++ b/rhacs/4.3.8/central-services/internal/defaults.yaml @@ -0,0 +1,175 @@ +defaults: + + imagePullSecrets: + allowNone: true + useExisting: [] + useFromDefaultServiceAccount: true + + image: + registry: registry.redhat.io/advanced-cluster-security + + env: + offlineMode: false + + central: + config: "@config/central/config.yaml|config/central/config.yaml.default" + endpointsConfig: "@config/central/endpoints.yaml|config/central/endpoints.yaml.default" + + exposeMonitoring: false + + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Central is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + + image: + name: rhacs-main-rhel8 + tag: 4.3.8 + + resources: + requests: + memory: "4Gi" + cpu: "1500m" + limits: + memory: "8Gi" + cpu: "4000m" + + exposure: + loadBalancer: + enabled: false + port: 443 + nodePort: + enabled: false + port: null + route: + enabled: false + db: + external: false + + source: + minConns: 10 + maxConns: 90 + statementTimeoutMs: 1200000 + + postgresConfig: "@config/centraldb/postgresql.conf|config/centraldb/postgresql.conf.default" + hbaConfig: "@config/centraldb/pg_hba.conf|config/centraldb/pg_hba.conf.default" + + image: + name: rhacs-central-db-rhel8 + tag: 4.3.8 + + resources: + requests: + memory: "8Gi" + cpu: "4" + limits: + memory: "16Gi" + cpu: "8" + scanner: + disable: false + replicas: 3 + logLevel: INFO + mode: full + + autoscaling: + disable: false + minReplicas: 2 + maxReplicas: 5 + + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: + app: scanner + topologyKey: kubernetes.io/hostname + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + + resources: + requests: + memory: "1500Mi" + cpu: "1000m" + limits: + memory: "4Gi" + cpu: "2000m" + + image: + name: rhacs-scanner-rhel8 + tag: 4.3.8 + + dbResources: + limits: + cpu: "2000m" + memory: "4Gi" + requests: + cpu: "200m" + memory: "200Mi" + + dbImage: + name: rhacs-scanner-db-rhel8 + tag: 4.3.8 + + system: + createSCCs: true + +pvcDefaults: + claimName: "stackrox-db" + size: "100Gi" + +dbPVCDefaults: + claimName: "central-db" + size: "100Gi" diff --git a/rhacs/4.3.8/central-services/internal/expandables.yaml b/rhacs/4.3.8/central-services/internal/expandables.yaml new file mode 100644 index 0000000..75a3d11 --- /dev/null +++ b/rhacs/4.3.8/central-services/internal/expandables.yaml @@ -0,0 +1,48 @@ +licenseKey: true +imagePullSecrets: + username: true + password: true +env: + proxyConfig: true +ca: + cert: true + key: true +central: + config: true + endpointsConfig: true + nodeSelector: true + jwtSigner: + key: true + serviceTLS: + cert: true + key: true + defaultTLS: + cert: true + key: true + adminPassword: + value: true + htpasswd: true + resources: true + db: + postgresConfig: true + hbaConfig: true + nodeSelector: true + serviceTLS: + cert: true + key: true + password: + value: true + resources: true +scanner: + resources: true + dbResources: true + nodeSelector: true + dbNodeSelector: true + dbPassword: + value: true + serviceTLS: + cert: true + key: true + dbServiceTLS: + cert: true + key: true diff --git a/rhacs/4.3.8/central-services/internal/platforms/default.yaml b/rhacs/4.3.8/central-services/internal/platforms/default.yaml new file mode 100644 index 0000000..180f5c8 --- /dev/null +++ b/rhacs/4.3.8/central-services/internal/platforms/default.yaml @@ -0,0 +1,2 @@ +# Empty defaults file for the "default" platform. This file only exists to mark the platform +# name as valid. diff --git a/rhacs/4.3.8/central-services/internal/platforms/gke.yaml b/rhacs/4.3.8/central-services/internal/platforms/gke.yaml new file mode 100644 index 0000000..70d7b32 --- /dev/null +++ b/rhacs/4.3.8/central-services/internal/platforms/gke.yaml @@ -0,0 +1,2 @@ +pvcDefaults: + storageClass: "stackrox-gke-ssd" diff --git a/rhacs/4.3.8/central-services/internal/scanner-config-shape.yaml b/rhacs/4.3.8/central-services/internal/scanner-config-shape.yaml new file mode 100644 index 0000000..da3b315 --- /dev/null +++ b/rhacs/4.3.8/central-services/internal/scanner-config-shape.yaml @@ -0,0 +1,40 @@ +scanner: + mode: null # string + disable: null # bool + replicas: null # int + logLevel: null # string + nodeSelector: null # string | dict + dbNodeSelector: null # string | dict + tolerations: null # [dict] + dbTolerations: null # [dict] + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + affinity: null # dict + resources: null # string | dict + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + dbImage: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + dbResources: null # string | dict + dbPassword: + value: null # string + generate: null # bool + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + dbServiceTLS: + cert: null # string + key: null # string + generate: null # bool + exposeMonitoring: null # bool +system: + enablePodSecurityPolicies: null # bool diff --git a/rhacs/4.3.8/central-services/templates/00-additional-ca.yaml b/rhacs/4.3.8/central-services/templates/00-additional-ca.yaml new file mode 100644 index 0000000..67b0c2b --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/00-additional-ca.yaml @@ -0,0 +1,21 @@ +{{- include "srox.init" . -}} + +{{- if ._rox._additionalCAs }} +apiVersion: v1 +kind: Secret +metadata: + name: additional-ca + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "additional-ca") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "additional-ca") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + {{- range $name, $cert := ._rox._additionalCAs }} + {{ $name | quote }}: | + {{- $cert | nindent 4 }} + {{- end }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/00-image-pull-secret.yaml b/rhacs/4.3.8/central-services/templates/00-image-pull-secret.yaml new file mode 100644 index 0000000..1fc3e34 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/00-image-pull-secret.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.imagePullSecrets._dockerAuths }} +apiVersion: v1 +kind: Secret +type: kubernetes.io/dockerconfigjson +metadata: + name: stackrox + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "stackrox") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "stackrox") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +data: + .dockerconfigjson: {{ dict "auths" ._rox.imagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/00-injected-ca-bundle.yaml b/rhacs/4.3.8/central-services/templates/00-injected-ca-bundle.yaml new file mode 100644 index 0000000..3289c2a --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/00-injected-ca-bundle.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} + +{{- if eq ._rox.env.openshift 4 }} +{{ $injectedCABundleName := printf "injected-cabundle-%s" .Release.Name }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $injectedCABundleName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" $injectedCABundleName) | nindent 4 }} + "config.openshift.io/inject-trusted-cabundle": "true" + annotations: + {{- include "srox.annotations" (list . "configmap" $injectedCABundleName) | nindent 4 }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/00-proxy-config-secret.yaml b/rhacs/4.3.8/central-services/templates/00-proxy-config-secret.yaml new file mode 100644 index 0000000..c357179 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/00-proxy-config-secret.yaml @@ -0,0 +1,20 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.env._proxyConfig -}} +apiVersion: v1 +kind: Secret +metadata: + name: proxy-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "proxy-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "proxy-config") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + config.yaml: | + {{- ._rox.env._proxyConfig | nindent 4 }} + +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/00-stackrox-application.yaml b/rhacs/4.3.8/central-services/templates/00-stackrox-application.yaml new file mode 100644 index 0000000..6cdf9ca --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/00-stackrox-application.yaml @@ -0,0 +1,122 @@ +{{- include "srox.init" . -}} + +{{- if has "app.k8s.io/v1beta1/Application" ._rox._apiServer.apiResources -}} +apiVersion: app.k8s.io/v1beta1 +kind: Application +metadata: + name: stackrox + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "application" "stackrox") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "application" "stackrox") | nindent 4 }} + {{ if eq ._rox.image.registry "quay.io/stackrox-io" }} + kubernetes-engine.cloud.google.com/icon: "data:image/png;base64,{{ .Files.Get "assets/StackRox_icon.png" | b64enc }}" + {{ else }} + kubernetes-engine.cloud.google.com/icon: "data:image/png;base64,{{ .Files.Get "assets/Red_Hat-Hat_icon.png" | b64enc }}" + {{ end }} +spec: + descriptor: + type: StackRox + version: {{ .Chart.AppVersion | quote }} + description: |- + StackRox Kubernetes Security Platform + + Version {{ .Chart.AppVersion }} + + ## Thank you for installing StackRox! + +
+ + #### Support + + [Email support@stackrox.com](mailto:support@stackrox.com?cc=sales@stackrox.com&Subject=StackRox%20Support%20Question&Body=Dear%20StackRox%20support,) + + ## Connecting to StackRox + +
+ + #### Directly using a Load Balancer + + When deploying StackRox with the `Load Balancer` network configuration, the service can be accessed directly. + + $CONNECT + + #### Tunneling via Port Forward + + When deploying StackRox with the `Node Port` or `None` network configuration, the service must be accessed using a port forward tunnel. + + - Step 1 - Start the port forward tunnel to the StackRox Central service. + + ``` + $ kubectl -n stackrox port-forward svc/central 8443:443 + ``` + + - Step 2 - In a browser, [visit https://localhost:8443](https://localhost:8443) to access StackRox. + + keywords: + - "stackrox" + - "kube" + - "security" + maintainers: + - name: StackRox, Inc. + url: https://stackrox.com + owners: + - name: StackRox, Inc. + url: https://stackrox.com + links: + - description: StackRox Help Documentation + url: "https://help.stackrox.com" + + info: + - name: StackRox namespace + value: stackrox + - name: StackRox admin username + value: "admin" + + selector: + matchLabels: + app.kubernetes.io/name: stackrox + + componentKinds: + - group: '' + kind: ConfigMap + - group: '' + kind: Secret + - group: '' + kind: PersistentVolumeClaim + - group: '' + kind: PersistentVolume + - group: '' + kind: Service + - group: '' + kind: ServiceAccount + - group: rbac.authorization.k8s.io + kind: ClusterRole + - group: rbac.authorization.k8s.io + kind: ClusterRoleBinding + - group: apps + kind: Deployment + - group: networking.k8s.io + kind: NetworkPolicy + - group: rbac.authorization.k8s.io + kind: Role + - group: rbac.authorization.k8s.io + kind: RoleBinding + - group: route.openshift.io + kind: Route + - group: security.openshift.io + kind: SecurityContextConstraints + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + - group: autoscaling + kind: HorizontalPodAutoscaler + - group: storage.k8s.io + kind: StorageClass + - group: networking.istio.io + kind: DestinationRule +{{- if ._rox.system.enablePodSecurityPolicies }} + - group: policy + kind: PodSecurityPolicy +{{- end }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/00-storage-class.yaml b/rhacs/4.3.8/central-services/templates/00-storage-class.yaml new file mode 100644 index 0000000..4a5664e --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/00-storage-class.yaml @@ -0,0 +1,27 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.central.persistence._pvcCfg }} +{{- if ._rox.central.persistence._pvcCfg.storageClass -}} +{{- if eq ._rox.central.persistence._pvcCfg.storageClass "stackrox-gke-ssd" }} +{{- $lookupOut := dict -}} +{{- $storageClassName := include "srox.globalResourceName" (list . "stackrox-gke-ssd") -}} +{{- $_ := include "srox.safeLookup" (list . $lookupOut "storage.k8s.io/v1" "StorageClass" "" $storageClassName) -}} +{{- if and (not $lookupOut.result) (or .Release.IsInstall $lookupOut.reliable) (not ._rox.meta.noCreateStorageClass) -}} +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ $storageClassName }} + labels: + {{- include "srox.labels" (list . "storageclass" "stackrox-gke-ssd") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "storageclass" "stackrox-gke-ssd") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +provisioner: kubernetes.io/gce-pd +parameters: + type: pd-ssd +{{- end -}} +{{- end }} +{{- end -}} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-00-db-serviceaccount.yaml b/rhacs/4.3.8/central-services/templates/01-central-00-db-serviceaccount.yaml new file mode 100644 index 0000000..782f4e6 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-00-db-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} +{{ if not ._rox.central.db.external -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: central-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "central-db") | nindent 4 }} +imagePullSecrets: + {{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} + {{- end }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-00-serviceaccount.yaml b/rhacs/4.3.8/central-services/templates/01-central-00-serviceaccount.yaml new file mode 100644 index 0000000..8c257f6 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-00-serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: central + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "central") | nindent 4 }} + {{- if and (eq ._rox.env.openshift 4) (not ._rox.env.managedServices) }} + serviceaccounts.openshift.io/oauth-redirectreference.main: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"central"}}' + serviceaccounts.openshift.io/oauth-redirecturi.main: "sso/providers/openshift/callback" + {{- end }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-01-license-secret.yaml b/rhacs/4.3.8/central-services/templates/01-central-01-license-secret.yaml new file mode 100644 index 0000000..0d26dda --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-01-license-secret.yaml @@ -0,0 +1,21 @@ +{{- include "srox.init" . -}} + +{{- if ._rox._licenseKey -}} + +apiVersion: v1 +kind: Secret +metadata: + name: central-license + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-license") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-license") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + license.lic: | + {{- ._rox._licenseKey | nindent 4 }} + +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-02-db-psps.yaml b/rhacs/4.3.8/central-services/templates/01-central-02-db-psps.yaml new file mode 100644 index 0000000..4c81428 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-02-db-psps.yaml @@ -0,0 +1,81 @@ +{{- include "srox.init" . -}} + +{{- if and (not ._rox.central.db.external) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central-db-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-central-db-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-central-db-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-central-db") }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-central-db-psp + namespace: {{.Release.Namespace}} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-central-db-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-central-db-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-central-db-psp") }} +subjects: + - kind: ServiceAccount + name: central-db + namespace: {{.Release.Namespace}} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central-db") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-central-db") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + - 'hostPath' + - 'configMap' + {{- if ._rox.central.persistence.hostPath }} + allowedHostPaths: + {{- /* TODO(ROX-9807): Use a designated path for central-db for now. Need to move hostPath from central to central-db */}} + - pathPrefix: {{._rox.central.persistence.hostPath}}-db + {{- end}} + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 70 + max: 70 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 70 + max: 70 +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-02-db-security.yaml b/rhacs/4.3.8/central-services/templates/01-central-02-db-security.yaml new file mode 100644 index 0000000..20ead97 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-02-db-security.yaml @@ -0,0 +1,82 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift (not ._rox.central.db.external) ._rox.system.createSCCs }} +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central-db") }} + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-central-db") | nindent 4 }} + annotations: + kubernetes.io/description: stackrox-central-db is the security constraint for the central database + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-central-db") | nindent 4 }} +allowHostDirVolumePlugin: {{ ._rox.central.persistence.hostPath | not | not }} +allowedCapabilities: [] +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +defaultAddCapabilities: [] +fsGroup: + type: MustRunAs + ranges: + - max: 70 + min: 70 +priority: 0 +readOnlyRootFilesystem: false +requiredDropCapabilities: [] +runAsUser: + type: MustRunAs + uid: 70 +seLinuxContext: + type: "RunAsAny" +seccompProfiles: + - '*' +users: + - system:serviceaccount:{{ .Release.Namespace }}:central-db +volumes: + - '*' +{{- else if eq ._rox.env.openshift 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-central-db-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-central-db-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-central-db-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - anyuid + {{- if ._rox.central.persistence.hostPath }} + - hostmount-anyuid + {{- end }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: central-db-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "central-db-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "central-db-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-central-db-scc +subjects: +- kind: ServiceAccount + name: central-db + namespace: {{.Release.Namespace}} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-02-psps.yaml b/rhacs/4.3.8/central-services/templates/01-central-02-psps.yaml new file mode 100644 index 0000000..1ba51f5 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-02-psps.yaml @@ -0,0 +1,80 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-central-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-central-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-central") }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-central-psp + namespace: {{.Release.Namespace}} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-central-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-central-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-central-psp") }} +subjects: + - kind: ServiceAccount + name: central + namespace: {{.Release.Namespace}} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-central") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + - 'hostPath' + {{ if ._rox.central.persistence.hostPath -}} + allowedHostPaths: + - pathPrefix: {{ ._rox.central.persistence.hostPath }} + {{- end}} + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-02-security.yaml b/rhacs/4.3.8/central-services/templates/01-central-02-security.yaml new file mode 100644 index 0000000..ee734a6 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-02-security.yaml @@ -0,0 +1,85 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} +--- + +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-central") }} + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-central") | nindent 4 }} + annotations: + kubernetes.io/description: stackrox-central is the security constraint for the central server + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-central") | nindent 4 }} +allowHostDirVolumePlugin: {{ ._rox.central.persistence.hostPath | not | not }} +allowedCapabilities: [] +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +defaultAddCapabilities: [] +fsGroup: + type: MustRunAs + ranges: + - max: 4000 + min: 4000 +priority: 0 +readOnlyRootFilesystem: true +requiredDropCapabilities: [] +runAsUser: + type: MustRunAs + uid: 4000 +seLinuxContext: + type: MustRunAs +seccompProfiles: + - '*' +users: + - system:serviceaccount:{{ .Release.Namespace }}:central +volumes: + - '*' + +{{- else if eq ._rox.env.openshift 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-central-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-central-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-central-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - anyuid + {{- if ._rox.central.persistence.hostPath }} + - hostmount-anyuid + {{- end }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: central-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "central-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "central-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-central-scc +subjects: +- kind: ServiceAccount + name: central + namespace: {{.Release.Namespace}} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-03-diagnostics-rbac.yaml b/rhacs/4.3.8/central-services/templates/01-central-03-diagnostics-rbac.yaml new file mode 100644 index 0000000..4c83007 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-03-diagnostics-rbac.yaml @@ -0,0 +1,45 @@ +{{- include "srox.init" . -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: stackrox-central-diagnostics + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "stackrox-central-diagnostics") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "stackrox-central-diagnostics") | nindent 4 }} +rules: +- apiGroups: + - '*' + resources: + - "deployments" + - "daemonsets" + - "replicasets" + - "configmaps" + - "services" + - "pods" + - "pods/log" + - "events" + - "namespaces" + verbs: + - get + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-central-diagnostics + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-central-diagnostics") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-central-diagnostics") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: stackrox-central-diagnostics +subjects: + - kind: ServiceAccount + name: central + namespace: {{ .Release.Namespace }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-04-htpasswd-secret.yaml b/rhacs/4.3.8/central-services/templates/01-central-04-htpasswd-secret.yaml new file mode 100644 index 0000000..59b338e --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-04-htpasswd-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.central._adminPassword -}} +{{- if ._rox.central._adminPassword.htpasswd -}} +apiVersion: v1 +kind: Secret +metadata: + name: central-htpasswd + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-htpasswd") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-htpasswd") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + htpasswd: | + {{- ._rox.central._adminPassword.htpasswd | nindent 4 }} + +{{- end -}} +{{- end -}} diff --git a/rhacs/4.3.8/central-services/templates/01-central-05-db-tls-secret.yaml b/rhacs/4.3.8/central-services/templates/01-central-05-db-tls-secret.yaml new file mode 100644 index 0000000..3a3a1fa --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-05-db-tls-secret.yaml @@ -0,0 +1,23 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.central.db._serviceTLS ._rox._ca }} +apiVersion: v1 +kind: Secret +metadata: + name: central-db-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-db-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-db-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox._ca.Cert | nindent 4 }} + cert.pem: | + {{- ._rox.central.db._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.central.db._serviceTLS.Key | nindent 4 }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-05-tls-secret.yaml b/rhacs/4.3.8/central-services/templates/01-central-05-tls-secret.yaml new file mode 100644 index 0000000..1850d46 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-05-tls-secret.yaml @@ -0,0 +1,30 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox._ca ._rox.central._serviceTLS ._rox.central._jwtSigner -}} + +apiVersion: v1 +kind: Secret +metadata: + name: central-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox._ca.Cert | nindent 4 }} + ca-key.pem: | + {{- ._rox._ca.Key | nindent 4 }} + jwt-key.pem: | + {{- ._rox.central._jwtSigner.Key | nindent 4 }} + cert.pem: | + {{- ._rox.central._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.central._serviceTLS.Key | nindent 4 }} +{{- else if or ._rox.central._serviceTLS ._rox.central._jwtSigner }} +{{ include "srox.fail" "Service TLS certificates and/or JWT signer key can only be created/updated if all data AND the service CA are present/specified." }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-06-default-tls-cert-secret.yaml b/rhacs/4.3.8/central-services/templates/01-central-06-default-tls-cert-secret.yaml new file mode 100644 index 0000000..010444c --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-06-default-tls-cert-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} + +{{ if ._rox.central._defaultTLS }} + +apiVersion: v1 +kind: Secret +metadata: + name: central-default-tls-cert + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-default-tls-cert") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-default-tls-cert") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" +type: kubernetes.io/tls +stringData: + tls.crt: | + {{- ._rox.central._defaultTLS.Cert | nindent 4 }} + tls.key: | + {{- ._rox.central._defaultTLS.Key | nindent 4 }} + +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-08-configmap.yaml b/rhacs/4.3.8/central-services/templates/01-central-08-configmap.yaml new file mode 100644 index 0000000..9420e59 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-08-configmap.yaml @@ -0,0 +1,14 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: central-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "central-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "central-config") | nindent 4 }} +data: + central-config.yaml: | + {{- ._rox.central._config | nindent 4 }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-08-db-configmap.yaml b/rhacs/4.3.8/central-services/templates/01-central-08-db-configmap.yaml new file mode 100644 index 0000000..0a0a2c7 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-08-db-configmap.yaml @@ -0,0 +1,17 @@ +{{- include "srox.init" . -}} +{{- if not ._rox.central.db.external }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: central-db-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "central-db-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "central-db-config") | nindent 4 }} +data: + postgresql.conf: | + {{- ._rox.central.db._postgresConfig | nindent 4 }} + pg_hba.conf: | + {{- ._rox.central.db._hbaConfig | nindent 4 }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-08-external-db-configmap.yaml b/rhacs/4.3.8/central-services/templates/01-central-08-external-db-configmap.yaml new file mode 100644 index 0000000..48d2427 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-08-external-db-configmap.yaml @@ -0,0 +1,29 @@ +{{- include "srox.init" . -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: central-external-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "central-external-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "central-external-db") | nindent 4 }} +data: + central-external-db.yaml: | + centralDB: + {{- if ._rox.central.db.external }} + external: true + source: {{ ._rox.central.db.source.connectionString }} pool_min_conns={{ ._rox.central.db.source.minConns }} pool_max_conns={{ ._rox.central.db.source.maxConns }} + {{- else }} + external: false + source: > + host=central-db.{{ .Release.Namespace }}.svc + port=5432 + user=postgres + sslmode={{- if eq .Release.Namespace "stackrox" }}verify-full{{- else }}verify-ca{{- end }} + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + statement_timeout={{ ._rox.central.db.source.statementTimeoutMs }} + pool_min_conns={{ ._rox.central.db.source.minConns }} + pool_max_conns={{ ._rox.central.db.source.maxConns }} + client_encoding=UTF8 + {{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-09-endpoints-config.yaml b/rhacs/4.3.8/central-services/templates/01-central-09-endpoints-config.yaml new file mode 100644 index 0000000..fa6204e --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-09-endpoints-config.yaml @@ -0,0 +1,17 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.central._endpointsConfig -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: central-endpoints + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "central-endpoints") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "central-endpoints") | nindent 4 }} +data: + endpoints.yaml: | + {{- ._rox.central._endpointsConfig | nindent 4 }} + +{{- end -}} diff --git a/rhacs/4.3.8/central-services/templates/01-central-10-db-networkpolicy.yaml b/rhacs/4.3.8/central-services/templates/01-central-10-db-networkpolicy.yaml new file mode 100644 index 0000000..6cd2201 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-10-db-networkpolicy.yaml @@ -0,0 +1,27 @@ +{{- include "srox.init" . -}} +{{ if not ._rox.central.db.external -}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: central-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "central-db") | nindent 4 }} +spec: + policyTypes: + - Ingress + - Egress + ingress: + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 5432 + protocol: TCP + podSelector: + matchLabels: + app: central-db +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-10-networkpolicy.yaml b/rhacs/4.3.8/central-services/templates/01-central-10-networkpolicy.yaml new file mode 100644 index 0000000..90fbd9d --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-10-networkpolicy.yaml @@ -0,0 +1,65 @@ +{{- include "srox.init" . -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-ext-to-central + namespace: {{.Release.Namespace}} + labels: + {{- include "srox.labels" (list . "networkpolicy" "allow-ext-to-central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "allow-ext-to-central") | nindent 4 }} +spec: + ingress: + {{- toYaml ._rox.central._netPolIngressRules | nindent 4 }} + podSelector: + matchLabels: + app: central + policyTypes: + - Ingress + +{{ if ._rox.central.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: central-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "central-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "central-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: central + policyTypes: + - Ingress +{{ end }} + +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: central-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "central-monitoring-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "central-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: central + policyTypes: + - Ingress +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-11-db-pvc.yaml b/rhacs/4.3.8/central-services/templates/01-central-11-db-pvc.yaml new file mode 100644 index 0000000..656dfec --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-11-db-pvc.yaml @@ -0,0 +1,66 @@ +{{- include "srox.init" . -}} + +{{ if not ._rox.central.db.external -}} +{{ if ._rox.central.db.persistence._pvcCfg -}} +{{- $pvcCfg := ._rox.central.db.persistence._pvcCfg -}} +{{- $claimName := $pvcCfg.claimName -}} +{{/* In a multiple namespace setting, storageClassName is generated by globalResourceName */}} +{{- $storageClassName := "" }} +{{- if $pvcCfg.storageClass }} + {{- if eq $pvcCfg.storageClass "stackrox-gke-ssd" }} + {{- $storageClassName = include "srox.globalResourceName" (list . "stackrox-gke-ssd") }} + {{- else }} + {{- $storageClassName = $pvcCfg.storageClass }} +{{- end}} +{{- end}} +{{- if $pvcCfg.volume.volumeSpec }} +{{- $pvName := (print $claimName "-pv") -}} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ $pvName }} + labels: + {{- include "srox.labels" (list . "persistentvolume" $pvName) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolume" $pvName) | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end}} + capacity: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} + accessModes: + - ReadWriteOnce + claimRef: + namespace: {{ .Release.Namespace }} + name: {{ $claimName }} + {{- toYaml $pvcCfg.volume.volumeSpec | nindent 2 }} +--- +{{- end }} +{{- /* TODO(ROX-9807): Move customized PVC from Central to Central DB */}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ $claimName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "persistentvolumeclaim" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolumeclaim" "central-db") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-11-pvc.yaml b/rhacs/4.3.8/central-services/templates/01-central-11-pvc.yaml new file mode 100644 index 0000000..0279278 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-11-pvc.yaml @@ -0,0 +1,63 @@ +{{- include "srox.init" . -}} + +{{ if ._rox.central.persistence._pvcCfg -}} +{{- $pvcCfg := ._rox.central.persistence._pvcCfg -}} +{{- $claimName := $pvcCfg.claimName -}} +{{/* In a multiple namespace setting, storageClassName is generated by globalResourceName */}} +{{- $storageClassName := "" }} +{{- if $pvcCfg.storageClass }} + {{- if eq $pvcCfg.storageClass "stackrox-gke-ssd" }} + {{- $storageClassName = include "srox.globalResourceName" (list . "stackrox-gke-ssd") }} + {{- else }} + {{- $storageClassName = $pvcCfg.storageClass }} + {{- end}} +{{- end}} +{{- if $pvcCfg.volume.volumeSpec }} +{{- $pvName := (print $claimName "-pv") -}} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ $pvName }} + labels: + {{- include "srox.labels" (list . "persistentvolume" $pvName) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolume" $pvName) | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end}} + capacity: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} + accessModes: + - ReadWriteOnce + claimRef: + namespace: {{ .Release.Namespace }} + name: {{ $claimName }} + {{- toYaml $pvcCfg.volume.volumeSpec | nindent 2 }} +--- +{{- end }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ $claimName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "persistentvolumeclaim" $claimName) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolumeclaim" $claimName) | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep + "helm.sh/hook-delete-policy": never +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-12-central-db.yaml b/rhacs/4.3.8/central-services/templates/01-central-12-central-db.yaml new file mode 100644 index 0000000..e48b466 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-12-central-db.yaml @@ -0,0 +1,196 @@ +{{- include "srox.init" . -}} + +{{ if not ._rox.central.db.external -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: central-db + namespace: {{ .Release.Namespace }} + labels: + app: central-db + {{- include "srox.labels" (list . "deployment" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "central-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: central-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: central-db + {{- include "srox.podLabels" (list . "deployment" "central-db") | nindent 8 }} + annotations: + {{- include "srox.podAnnotations" (list . "deployment" "central-db") | nindent 8 }} + spec: + {{- if ._rox.central.db._nodeSelector }} + nodeSelector: + {{- ._rox.central.db._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.central.db.tolerations }} + tolerations: + {{- toYaml ._rox.central.db.tolerations | nindent 8 }} + {{- end }} + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Central-db is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + serviceAccountName: central-db + terminationGracePeriodSeconds: 120 + initContainers: + - name: init-db + image: {{ ._rox.central.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + command: + - init-entrypoint.sh + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: central-db-password + mountPath: /run/secrets/stackrox.io/secrets + resources: + {{- ._rox.central.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + containers: + - name: central-db + image: {{ ._rox.central.db.image.fullRef | quote }} + env: + - name: POSTGRES_HOST_AUTH_METHOD + value: "password" + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + ports: + - containerPort: 5432 + name: postgresql + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -c + - -e + - | + exec pg_isready -U "postgres" -h 127.0.0.1 -p 5432 + failureThreshold: 3 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + {{- ._rox.central.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + volumeMounts: + - name: config-volume + mountPath: /etc/stackrox.d/config/ + - mountPath: /var/lib/postgresql/data + name: disk + - name: central-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + - mountPath: /dev/shm + name: shared-memory + securityContext: + fsGroup: 70 + volumes: + - name: disk + {{- toYaml ._rox.central.db.persistence._volumeCfg | nindent 8 }} + - name: config-volume + configMap: + name: {{ default "central-db-config" ._rox.central.db.configOverride }} + - name: central-db-password + secret: + secretName: central-db-password + - name: central-db-tls-volume + secret: + secretName: central-db-tls + defaultMode: 0640 + items: + - key: cert.pem + path: server.crt + - key: key.pem + path: server.key + - key: ca.pem + path: root.crt + - name: shared-memory + emptyDir: + medium: Memory + {{- /* Keep this in sync with shared_buffers in config/centraldb/postgresql.conf */}} + sizeLimit: 2Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: central-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "central-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "central-db") | nindent 4 }} +spec: + ports: + - name: tcp-db + port: 5432 + protocol: TCP + targetPort: postgresql + selector: + app: central-db + type: ClusterIP +{{- end }} +{{- if ._rox.central.db._password }} +{{- if not (kindIs "invalid" ._rox.central.db._password.value) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: central-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "central-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "central-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.central.db._password.value | nindent 4 }} +{{- end }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-13-deployment.yaml b/rhacs/4.3.8/central-services/templates/01-central-13-deployment.yaml new file mode 100644 index 0000000..f56a974 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-13-deployment.yaml @@ -0,0 +1,271 @@ +{{- include "srox.init" . -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: central + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "deployment" "central") | nindent 4 }} + app: central + annotations: + {{- include "srox.annotations" (list . "deployment" "central") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: central + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: central + {{- include "srox.podLabels" (list . "deployment" "central") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8443" + {{- include "srox.podAnnotations" (list . "deployment" "central") | nindent 8 }} + spec: + {{- if ._rox.central._nodeSelector }} + nodeSelector: + {{- ._rox.central._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.central.tolerations }} + tolerations: + {{- toYaml ._rox.central.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.central.affinity | nindent 8 }} + serviceAccountName: central + securityContext: + fsGroup: 4000 + runAsUser: 4000 + containers: + - name: central + image: {{ ._rox.central.image.fullRef | quote }} + command: + - /stackrox/central-entrypoint.sh + ports: + {{- toYaml ._rox.central._containerPorts | nindent 10 }} + readinessProbe: + httpGet: + scheme: HTTPS + path: /v1/ping + port: 8443 + resources: + {{- ._rox.central._resources | nindent 10 }} + securityContext: + capabilities: + drop: ["NET_RAW"] + readOnlyRootFilesystem: true + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if ne (._rox.central.telemetry.enabled | toString) "false" }} + {{- if ._rox.central.telemetry.storage.endpoint }} + - name: ROX_TELEMETRY_ENDPOINT + value: {{ ._rox.central.telemetry.storage.endpoint | quote }} + {{- end }} + {{- if ._rox.central.telemetry.storage.key }} + - name: ROX_TELEMETRY_STORAGE_KEY_V1 + value: {{ ._rox.central.telemetry.storage.key | quote }} + {{- end }} + {{- end }} + - name: ROX_OFFLINE_MODE + value: {{ ._rox.env.offlineMode | quote }} + {{- if and (eq ._rox.env.openshift 4) (not ._rox.env.managedServices) }} + - name: ROX_ENABLE_OPENSHIFT_AUTH + value: "true" + {{- end }} + {{- if ._rox.env.openshift }} + - name: ROX_OPENSHIFT + value: "true" + {{- end }} + {{- if ._rox.env.managedServices }} + - name: ROX_MANAGED_CENTRAL + value: "true" + - name: ROX_ENABLE_CENTRAL_DIAGNOSTICS + value: "false" + - name: ROX_ENABLE_KERNEL_PACKAGE_UPLOAD + value: "false" + - name: ROX_TENANT_ID + valueFrom: + fieldRef: + fieldPath: metadata.labels['rhacs.redhat.com/tenant'] + {{- end }} + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: ROX_ENC_NOTIFIER_CREDS + value: "true" + {{- end }} + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + {{- end }} + - name: ROX_INSTALL_METHOD + value: {{ ._rox.env.installMethod | quote }} + {{- include "srox.envVars" (list . "deployment" "central" "central") | nindent 8 }} + volumeMounts: + - name: varlog + mountPath: /var/log/stackrox/ + - name: central-tmp-volume + mountPath: /tmp + - name: central-etc-ssl-volume + mountPath: /etc/ssl + - name: central-etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: central-certs-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: central-default-tls-cert-volume + mountPath: /run/secrets/stackrox.io/default-tls-cert/ + readOnly: true + - name: central-htpasswd-volume + mountPath: /run/secrets/stackrox.io/htpasswd/ + readOnly: true + - name: central-jwt-volume + mountPath: /run/secrets/stackrox.io/jwt/ + readOnly: true + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: central-license-volume + mountPath: /run/secrets/stackrox.io/central-license/ + readOnly: true + - name: stackrox-db + mountPath: /var/lib/stackrox + - name: central-config-volume + mountPath: /etc/stackrox + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: endpoints-config-volume + mountPath: /etc/stackrox.d/endpoints/ + readOnly: true + - name: central-db-password + mountPath: /run/secrets/stackrox.io/db-password + - name: central-external-db-volume + mountPath: /etc/ext-db + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: central-encryption-key + mountPath: /run/secrets/stackrox.io/central-encryption-key + {{- end }} + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + {{- range $extraMount := (default list ._rox.central.extraMounts) }} + - name: {{ $extraMount.name }} + {{- $extraMount.mount | toYaml | nindent 10 }} + {{- end }} + {{- range $mount := (default list ._rox.central.declarativeConfiguration.mounts.configMaps) }} + - name: {{ $mount }} + mountPath: /run/stackrox.io/declarative-configuration/{{ $mount }} + readOnly: true + {{- end }} + {{- range $mount := (default list ._rox.central.declarativeConfiguration.mounts.secrets) }} + - name: {{ $mount }} + mountPath: /run/stackrox.io/declarative-configuration/{{ $mount }} + readOnly: true + {{- end }} + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + volumes: + - name: varlog + emptyDir: {} + - name: central-tmp-volume + emptyDir: {} + - name: central-etc-ssl-volume + emptyDir: {} + - name: central-etc-pki-volume + emptyDir: {} + - name: central-certs-volume + secret: + secretName: central-tls + - name: central-default-tls-cert-volume + secret: + secretName: {{ default "central-default-tls-cert" ._rox.central.defaultTLS.reference }} + optional: true + - name: central-htpasswd-volume + secret: + secretName: central-htpasswd + optional: true + - name: central-jwt-volume + secret: + secretName: central-tls + items: + - key: jwt-key.pem + path: jwt-key.pem + - name: additional-ca-volume + secret: + secretName: additional-ca + optional: true + - name: central-license-volume + secret: + secretName: central-license + optional: true + - name: central-config-volume + configMap: + name: central-config + optional: true + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: endpoints-config-volume + configMap: + name: central-endpoints + - name: central-db-password + secret: + secretName: central-db-password + - name: central-external-db-volume + configMap: + name: central-external-db + optional: true + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: central-encryption-key + secret: + secretName: central-encryption-key + {{- end }} + {{- end }} + - name: stackrox-db + {{- toYaml ._rox.central.persistence._volumeCfg | nindent 8 }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: central-monitoring-tls + optional: true + {{- end }} + {{- range $extraMount := (default list ._rox.central.extraMounts) }} + - name: {{ $extraMount.name }} + {{- $extraMount.source | toYaml | nindent 8 }} + {{- end }} + {{- range $mount := (default list ._rox.central.declarativeConfiguration.mounts.configMaps) }} + - name: {{ $mount }} + configMap: + name: {{ $mount }} + optional: true + {{- end }} + {{- range $mount := (default list ._rox.central.declarativeConfiguration.mounts.secrets) }} + - name: {{ $mount }} + secret: + secretName: {{ $mount }} + optional: true + {{- end }} + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-14-service.yaml b/rhacs/4.3.8/central-services/templates/01-central-14-service.yaml new file mode 100644 index 0000000..f459fd7 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-14-service.yaml @@ -0,0 +1,43 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: Service +metadata: + name: central + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "central") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: central-monitoring-tls + {{- end }} +spec: + ports: + {{- toYaml ._rox.central._servicePorts | nindent 4 }} + selector: + app: central + type: ClusterIP + +{{ if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: central-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "central-internal-no-istio-mtls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "destinationrule" "central-internal-no-istio-mtls") | nindent 4 }} + stackrox.io/description: "Disable Istio mTLS for port 443, since StackRox services use built-in mTLS." +spec: + host: central.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 443 + tls: + mode: DISABLE +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/01-central-15-exposure.yaml b/rhacs/4.3.8/central-services/templates/01-central-15-exposure.yaml new file mode 100644 index 0000000..9bfdbbb --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/01-central-15-exposure.yaml @@ -0,0 +1,95 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.central.exposure.route.enabled }} +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: central + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "route" "central") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "route" "central") | nindent 4 }} +spec: +{{- if ._rox.central.exposure.route.host }} + host: {{ ._rox.central.exposure.route.host }} +{{- end }} + port: + targetPort: https + tls: + termination: passthrough + to: + kind: Service + name: central +--- +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: central-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "route" "central-mtls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "route" "central-mtls") | nindent 4 }} +spec: + host: "central.{{ .Release.Namespace }}" + port: + targetPort: https + tls: + termination: passthrough + to: + kind: Service + name: central +--- +{{- end }} + +{{- if ._rox.central.exposure.nodePort.enabled }} +apiVersion: v1 +kind: Service +metadata: + annotations: + {{- include "srox.annotations" (list . "service" "central-loadbalancer") | nindent 4 }} + cloud.google.com/app-protocols: '{"api": "HTTPS"}' + service.alpha.kubernetes.io/app-protocols: '{"api": "HTTPS"}' + name: central-loadbalancer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "central-loadbalancer") | nindent 4 }} +spec: + type: NodePort + ports: + - port: 443 + targetPort: api +{{- if ._rox.central.exposure.nodePort.port }} + nodePort: {{ ._rox.central.exposure.nodePort.port }} +{{- end }} + selector: + app: central +--- +{{- end }} + +{{- if ._rox.central.exposure.loadBalancer.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: central-loadbalancer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "central-loadbalancer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "central-loadbalancer") | nindent 4 }} +spec: + type: LoadBalancer + # This ensures that the client source IP is retained for audit logging purposes. + # Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + externalTrafficPolicy: Local + ports: + - port: {{ ._rox.central.exposure.loadBalancer.port }} + targetPort: api + selector: + app: central +{{- if ._rox.central.exposure.loadBalancer.ip }} + loadBalancerIP: {{ ._rox.central.exposure.loadBalancer.ip }} +{{- end }} +--- +{{- end}} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-00-serviceaccount.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-00-serviceaccount.yaml new file mode 100644 index 0000000..a27c602 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-00-serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "scanner") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} + +{{ end -}} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-01-psps.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-01-psps.yaml new file mode 100644 index 0000000..23b398c --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-01-psps.yaml @@ -0,0 +1,69 @@ +{{- include "srox.init" . -}} + +{{- if and (not ._rox.scanner.disable) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-scanner-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-scanner-psp") | nindent 4 }} +rules: +- apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-scanner-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-scanner-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-scanner-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-psp") }} +subjects: + - kind: ServiceAccount + name: scanner + namespace: {{ .Release.Namespace }} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-scanner") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-01-security.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-01-security.yaml new file mode 100644 index 0000000..3c1d92b --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-01-security.yaml @@ -0,0 +1,78 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable }} +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-scanner") | nindent 4 }} + kubernetes.io/description: stackrox-scanner is the security constraint for the Scanner container +priority: 0 +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +users: + - system:serviceaccount:{{ .Release.Namespace }}:scanner +volumes: + - '*' +allowHostDirVolumePlugin: false +allowedCapabilities: [] +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +defaultAddCapabilities: [] +fsGroup: + type: RunAsAny +readOnlyRootFilesystem: false +requiredDropCapabilities: [] + +{{- else if eq ._rox.env.openshift 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-scanner-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-scanner-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-scanner-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - anyuid + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: scanner-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "scanner-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "scanner-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-scanner-scc +subjects: +- kind: ServiceAccount + name: scanner + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-02-db-password-secret.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-02-db-password-secret.yaml new file mode 100644 index 0000000..c6c0bc1 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-02-db-password-secret.yaml @@ -0,0 +1,27 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if ._rox.scanner._dbPassword -}} +{{- if not (kindIs "invalid" ._rox.scanner._dbPassword.value) -}} + +apiVersion: v1 +kind: Secret +metadata: + name: scanner-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.scanner._dbPassword.value | nindent 4 }} + +{{- end -}} +{{- end -}} + +{{ end -}} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-03-tls-secret.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-03-tls-secret.yaml new file mode 100644 index 0000000..7c590ff --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-03-tls-secret.yaml @@ -0,0 +1,55 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if and ._rox.scanner._serviceTLS ._rox._ca -}} + +apiVersion: v1 +kind: Secret +metadata: + name: scanner-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + ca.pem: | + {{- ._rox._ca.Cert | nindent 4 }} + cert.pem: | + {{- ._rox.scanner._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scanner._serviceTLS.Key | nindent 4 }} + +--- + +{{- end }} + +{{ if and ._rox.scanner._dbServiceTLS ._rox._ca -}} + +apiVersion: v1 +kind: Secret +metadata: + name: scanner-db-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-db-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-db-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox._ca.Cert | nindent 4 }} + cert.pem: | + {{- ._rox.scanner._dbServiceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scanner._dbServiceTLS.Key | nindent 4 }} + +{{- end -}} + +{{ end -}} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-04-scanner-config.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-04-scanner-config.yaml new file mode 100644 index 0000000..4ed16c7 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-04-scanner-config.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner/config.yaml.tpl") . | nindent 4 }} + +{{ end -}} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-05-network-policy.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-05-network-policy.yaml new file mode 100644 index 0000000..99f7233 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-05-network-policy.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner + ingress: + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP +{{ if or (eq ._rox.scanner.mode "slim") ._rox.env.openshift }} + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP +{{ end }} + policyTypes: + - Ingress + +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-db") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-db + ingress: + - from: + - podSelector: + matchLabels: + app: scanner + ports: + - port: 5432 + protocol: TCP + policyTypes: + - Ingress + +{{ end -}} + +{{ if ._rox.scanner.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: scanner + policyTypes: + - Ingress +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-06-deployment.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-06-deployment.yaml new file mode 100644 index 0000000..89ac82c --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-06-deployment.yaml @@ -0,0 +1,296 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + app: scanner + {{- include "srox.labels" (list . "deployment" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner") | nindent 4 }} +spec: + replicas: {{ ._rox.scanner.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner + {{- include "srox.podLabels" (list . "deployment" "scanner") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8080,8443" + {{- include "srox.podAnnotations" (list . "deployment" "scanner") | nindent 8 }} + spec: + {{- if ._rox.scanner._nodeSelector }} + nodeSelector: + {{- ._rox.scanner._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.tolerations }} + tolerations: + {{- toYaml ._rox.scanner.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scanner.affinity | nindent 8 }} + containers: + - name: scanner + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimImage.fullRef | quote }} + {{ else }} + image: {{ ._rox.scanner.image.fullRef | quote }} + {{ end -}} + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if ._rox.env.openshift }} + - name: ROX_OPENSHIFT_API + value: "true" + {{- end}} + {{- include "srox.envVars" (list . "deployment" "scanner" "scanner") | nindent 8 }} + resources: + {{- ._rox.scanner._resources | nindent 10 }} + command: + - /entrypoint.sh + ports: + - name: https + containerPort: 8080 + - name: grpc + containerPort: 8443 + {{ if ._rox.scanner.exposeMonitoring -}} + - name: monitoring + containerPort: 9090 + {{- end}} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /scanner/ping + port: 8080 + timeoutSeconds: 10 + periodSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + volumeMounts: + - name: scanner-etc-ssl-volume + mountPath: /etc/ssl + - name: scanner-etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: scanner-config-volume + mountPath: /etc/scanner + readOnly: true + - name: scanner-tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: vuln-temp-db + mountPath: /var/lib/stackrox + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: scanner-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner + volumes: + - name: additional-ca-volume + secret: + defaultMode: 420 + optional: true + secretName: additional-ca + - name: scanner-etc-ssl-volume + emptyDir: {} + - name: scanner-etc-pki-volume + emptyDir: {} + - name: scanner-config-volume + configMap: + name: scanner-config + - name: scanner-tls-volume + secret: + secretName: scanner-tls + - name: vuln-temp-db + emptyDir: {} + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: scanner-db-password + secret: + secretName: scanner-db-password + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + app: scanner-db + {{- include "srox.labels" (list . "deployment" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-db + {{- include "srox.podLabels" (list . "deployment" "scanner-db") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "5432" + {{- include "srox.podAnnotations" (list . "deployment" "scanner-db") | nindent 8 }} + spec: + {{- if ._rox.scanner._dbNodeSelector }} + nodeSelector: + {{- ._rox.scanner._dbNodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.dbTolerations }} + tolerations: + {{- toYaml ._rox.scanner.dbTolerations | nindent 8 }} + {{- end }} + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # ScannerDB is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + initContainers: + - name: init-db + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimDBImage.fullRef | quote }} + {{ else -}} + image: {{ ._rox.scanner.dbImage.fullRef | quote }} + {{ end -}} + env: + - name: POSTGRES_PASSWORD_FILE + value: "/run/secrets/stackrox.io/secrets/password" + - name: ROX_SCANNER_DB_INIT + value: "true" + resources: + {{- ._rox.scanner._dbResources | nindent 12 }} + volumeMounts: + - name: scanner-db-data + mountPath: /var/lib/postgresql/data + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + readOnly: true + - name: scanner-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + containers: + - name: db + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimDBImage.fullRef | quote }} + {{ else -}} + image: {{ ._rox.scanner.dbImage.fullRef | quote }} + {{ end -}} + env: + {{- include "srox.envVars" (list . "deployment" "scanner-db" "db") | nindent 10 }} + ports: + - name: tcp-postgresql + protocol: TCP + containerPort: 5432 + resources: + {{- ._rox.scanner._dbResources | nindent 10 }} + volumeMounts: + - name: scanner-db-data + mountPath: /var/lib/postgresql/data + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + readOnly: true + serviceAccountName: scanner + securityContext: + fsGroup: 70 + runAsGroup: 70 + runAsNonRoot: true + runAsUser: 70 + volumes: + - name: scanner-config-volume + configMap: + name: scanner-config + - name: scanner-tls-volume + secret: + secretName: scanner-tls + - name: scanner-db-tls-volume + secret: + secretName: scanner-db-tls + defaultMode: 0640 + items: + - key: cert.pem + path: server.crt + - key: key.pem + path: server.key + - key: ca.pem + path: root.crt + - name: scanner-db-data + emptyDir: {} + - name: scanner-db-password + secret: + secretName: scanner-db-password + +{{ end -}} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-07-service.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-07-service.yaml new file mode 100644 index 0000000..2f65b15 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-07-service.yaml @@ -0,0 +1,99 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: Service +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner") | nindent 4 }} +spec: + ports: + - name: https-scanner + port: 8080 + targetPort: 8080 + - name: grpcs-scanner + port: 8443 + targetPort: 8443 + {{ if ._rox.scanner.exposeMonitoring -}} + - name: monitoring + port: 9090 + targetPort: monitoring + {{- end}} + selector: + app: scanner + type: ClusterIP + +--- + +apiVersion: v1 +kind: Service +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-db") | nindent 4 }} +spec: + ports: + - name: tcp-db + port: 5432 + targetPort: 5432 + selector: + app: scanner-db + type: ClusterIP + +{{ if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for ports 8080 and 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8080 + tls: + mode: DISABLE + - port: + number: 8443 + tls: + mode: DISABLE + +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-db-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-db-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 5432, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-db-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-db.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 5432 + tls: + mode: DISABLE +{{ end }} + +{{ end -}} diff --git a/rhacs/4.3.8/central-services/templates/02-scanner-08-hpa.yaml b/rhacs/4.3.8/central-services/templates/02-scanner-08-hpa.yaml new file mode 100644 index 0000000..c7af476 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/02-scanner-08-hpa.yaml @@ -0,0 +1,25 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if not ._rox.scanner.autoscaling.disable -}} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scanner.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scanner.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner + targetCPUUtilizationPercentage: 150 +{{ end -}} + +{{ end -}} diff --git a/rhacs/4.3.8/central-services/templates/99-generated-values-secret.yaml b/rhacs/4.3.8/central-services/templates/99-generated-values-secret.yaml new file mode 100644 index 0000000..b3499e8 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/99-generated-values-secret.yaml @@ -0,0 +1,25 @@ +{{- include "srox.init" . -}} + +{{- if ._rox._state.generated -}} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ ._rox._state.generatedName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "generated-helm-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "generated-helm-config") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" + "helm.sh/hook-delete-policy": "never" +stringData: + generated-values.yaml: | + # The following values were generated by the StackRox Central Services Helm chart. + # You can pass this file to `helm install` via the `-f` parameter, which in conjunction + # with your local values files and values specified via `--set` will allow you to + # deterministically reproduce the deployment. + {{- ._rox._state.generated | toYaml | nindent 4 }} + +{{- end -}} diff --git a/rhacs/4.3.8/central-services/templates/99-openshift-monitoring.yaml b/rhacs/4.3.8/central-services/templates/99-openshift-monitoring.yaml new file mode 100644 index 0000000..e9c512e --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/99-openshift-monitoring.yaml @@ -0,0 +1,134 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.monitoring ._rox.monitoring.openshift ._rox.monitoring.openshift.enabled -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: central-prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "central-prometheus-k8s") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "central-prometheus-k8s") | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: central-prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "central-prometheus-k8s") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "central-prometheus-k8s") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: central-prometheus-k8s +subjects: +- kind: ServiceAccount + name: prometheus-k8s + namespace: openshift-monitoring + +--- + +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: "central-monitor-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "servicemonitor" (print "central-monitor-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "servicemonitor" (print "central-monitor-" .Release.Namespace)) | nindent 4 }} +spec: + endpoints: + - interval: 30s + path: metrics + port: monitoring-tls + scheme: https + tlsConfig: + caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt + certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt + keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key + serverName: "central.{{ .Release.Namespace }}.svc" + selector: + matchLabels: + app.kubernetes.io/component: central + namespaceSelector: + matchNames: + - "{{ .Release.Namespace }}" + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "rhacs-central-auth-reader-{{ .Release.Namespace }}" + namespace: kube-system + labels: + {{- include "srox.labels" (list . "rolebinding" (print "rhacs-central-auth-reader-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" (print "rhacs-central-auth-reader-" .Release.Namespace)) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: central + namespace: "{{ .Release.Namespace }}" + +--- + +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: "central-telemeter-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "prometheusrule" (print "central-telemeter-" .Release.Namespace )) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "prometheusrule" (print "central-telemeter-" .Release.Namespace )) | nindent 4 }} +spec: + groups: + - name: rhacs.telemeter + rules: + - expr: | + max by (build, central_id, central_version, hosting, install_method) ( + rox_central_info{branding="RHACS"} + ) + record: rhacs:telemetry:rox_central_info + + - expr: | + max by (central_id) ( + rox_central_secured_clusters{branding="RHACS"} + ) + record: rhacs:telemetry:rox_central_secured_clusters + + - expr: | + max by (central_id) ( + rox_central_secured_nodes{branding="RHACS"} + ) + record: rhacs:telemetry:rox_central_secured_nodes + + - expr: | + max by (central_id) ( + rox_central_secured_vcpus{branding="RHACS"} + ) + record: rhacs:telemetry:rox_central_secured_vcpus + +{{- end -}} diff --git a/rhacs/4.3.8/central-services/templates/NOTES.txt b/rhacs/4.3.8/central-services/templates/NOTES.txt new file mode 100644 index 0000000..27922b2 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/NOTES.txt @@ -0,0 +1,56 @@ +{{- $_ := include "srox.init" . -}} + +StackRox {{.Chart.AppVersion}} has been installed. + + +{{ if include "srox.checkGenerated" (list . "central.adminPassword.value") -}} +An administrator password has been generated automatically. Use username 'admin' and the following +password to log in for initial setup: + + {{ ._rox.central._adminPassword.value }} + +{{ end -}} + +{{ if ._rox._state.notes -}} +Please take note of the following: +{{ range ._rox._state.notes }} +- {{ . | wrapWith 98 "\n " -}} +{{ end }} + +{{ end -}} + +{{ if ._rox._state.generated -}} +One or several values were automatically generated by Helm. In order to reproduce this deployment +in the future, you can export these values by running + + $ kubectl -n {{ .Release.Namespace }} get secret {{ ._rox._state.generatedName }} \ + -o go-template='{{ `{{ index .data "generated-values.yaml" }}` }}' | \ + base64 --decode >generated-values.yaml + +This file might contain sensitive data, so store it in a safe place. + +{{ end -}} + +{{ if ._rox._state.warnings -}} +When installing StackRox, the following warnings were encountered: +{{ range ._rox._state.warnings }} +- WARNING: {{ . | wrapWith 98 "\n " -}} +{{ end }} + +{{ end -}} + +{{ if ._rox.env.openshift -}} +IMPORTANT: You have deployed into an OpenShift-enabled cluster. If you see that your pods + are not scheduling, run + + oc annotate namespace/{{ .Release.Namespace }} --overwrite openshift.io/node-selector="" +{{ end -}} + + +{{ if ne (._rox.central.telemetry.enabled | toString) "false" }} +StackRox Kubernetes Security Platform collects and transmits anonymous usage and +system configuration information. If you want to OPT OUT from this, use +--set central.telemetry.enabled=false. +{{ end }} + +Thank you for using StackRox! diff --git a/rhacs/4.3.8/central-services/templates/_central_endpoints.tpl b/rhacs/4.3.8/central-services/templates/_central_endpoints.tpl new file mode 100644 index 0000000..3bde7d4 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_central_endpoints.tpl @@ -0,0 +1,59 @@ +{{ define "srox.configureCentralEndpoints" }} +{{ $central := . }} +{{ $containerPorts := list (dict "name" "api" "containerPort" 8443) }} +{{ $netPolIngressRules := list (dict "ports" (list (dict "port" 8443 "protocol" "TCP"))) }} +{{ $servicePorts := list (dict "name" "https" "targetPort" "api" "port" 443) }} +{{ $cfgDict := fromYaml $central._endpointsConfig }} +{{ if kindIs "map" $cfgDict }} + {{ if $cfgDict.disableDefault }} + {{ $containerPorts = list }} + {{ $netPolIngressRules = list }} + {{ $servicePorts = list }} + {{ end }} + {{ range $epCfg := default list $cfgDict.endpoints }} + {{ if and $epCfg.listen (kindIs "string" $epCfg.listen) }} + {{ $listenParts := splitList ":" $epCfg.listen }} + {{ if $listenParts }} + {{ $port := last $listenParts }} + {{ if $port }} + {{ if regexMatch "[0-9]+" $port }} + {{ $port = int $port }} + {{ end }} + {{ $containerPort := dict "containerPort" $port }} + {{ if and $epCfg.name (kindIs "string" $epCfg.name) }} + {{ $_ := set $containerPort "name" $epCfg.name }} + {{ end }} + {{ $containerPorts = append $containerPorts $containerPort }} + {{ if $epCfg.servicePort }} + {{ $servicePort := dict "targetPort" $port "port" $epCfg.servicePort }} + {{ if $containerPort.name }} + {{ $_ := set $servicePort "name" $containerPort.name }} + {{ end }} + {{ $servicePorts = append $servicePorts $servicePort }} + {{ end }} + {{ if not (kindIs "invalid" $epCfg.allowIngressFrom) }} + {{ $fromList := $epCfg.allowIngressFrom }} + {{ if not (kindIs "slice" $fromList) }} + {{ $fromList = list $fromList }} + {{ end }} + {{ $netPolIngressRule := dict "ports" (list (dict "port" $port "protocol" "TCP")) "from" $fromList }} + {{ $netPolIngressRules = append $netPolIngressRules $netPolIngressRule }} + {{ end }} + {{ end }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ if $central.exposeMonitoring }} + {{ $containerPorts = append $containerPorts (dict "name" "monitoring" "containerPort" 9090) }} + {{ $servicePorts = append $servicePorts (dict "name" "monitoring" "targetPort" "monitoring" "port" 9090) }} +{{ end }} +# The (...) safe-guard against nil pointer evaluations for Helm versions built with Go < 1.18. +{{ if ((($central.monitoring).openshift).enabled) }} + {{ $containerPorts = append $containerPorts (dict "name" "monitoring-tls" "containerPort" 9091) }} + {{ $servicePorts = append $servicePorts (dict "name" "monitoring-tls" "targetPort" "monitoring-tls" "port" 9091) }} +{{ end }} +{{ $_ := set $central "_containerPorts" $containerPorts }} +{{ $_ = set $central "_servicePorts" $servicePorts }} +{{ $_ = set $central "_netPolIngressRules" $netPolIngressRules }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_central_setup.tpl b/rhacs/4.3.8/central-services/templates/_central_setup.tpl new file mode 100644 index 0000000..6584ad1 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_central_setup.tpl @@ -0,0 +1,140 @@ +{{/* + srox.centralSetup $ + + Configures and initializes central specific values like certificates, admin password or persistence. + */}} +{{ define "srox.centralSetup" }} +{{ $ := . }} +{{ $env := $._rox.env }} +{{ $_ := set $ "_rox" $._rox }} +{{ $centralCfg := $._rox.central }} +{{ $centralDBCfg := $._rox.central.db }} + +{{/* Image settings */}} +{{ include "srox.configureImage" (list $ $centralCfg.image) }} + +{{/* Admin password */}} +{{ include "srox.configurePassword" (list $ "central.adminPassword" "admin") }} + +{{/* Service TLS Certificates */}} +{{ $centralCertSpec := dict "CN" "CENTRAL_SERVICE: Central" "dnsBase" "central" }} +{{ include "srox.configureCrypto" (list $ "central.serviceTLS" $centralCertSpec) }} + +{{/* JWT Token Signer */}} +{{ $jwtSignerSpec := dict "keyOnly" "rsa" }} +{{ include "srox.configureCrypto" (list $ "central.jwtSigner" $jwtSignerSpec) }} + +{{/* Setup Default TLS Certificate. */}} +{{ if $._rox.central.defaultTLS }} + {{ $cert := $._rox.central.defaultTLS._cert }} + {{ $key := $._rox.central.defaultTLS._key }} + {{ if and $cert $key }} + {{ $defaultTLSCert := dict "Cert" $cert "Key" $key }} + {{ $_ := set $._rox.central "_defaultTLS" $defaultTLSCert }} + {{ include "srox.note" (list $ "Configured default TLS certificate") }} + {{ else if or $cert $key }} + {{ include "srox.fail" "Must specify either none or both of central.defaultTLS.cert and central.defaultTLS.key" }} + {{ end }} +{{ end }} + +{{/* Central DB password */}} +{{/* Always set up the password for Postgres if it is enabled */}} +{{ include "srox.configurePassword" (list $ "central.db.password") }} +{{ if not $centralDBCfg.external }} +{{ include "srox.configureImage" (list $ $centralDBCfg.image) }} + +{{/* Central DB Service TLS Certificates */}} +{{ $centralDBCertSpec := dict "CN" "CENTRAL_DB_SERVICE: Central DB" "dnsBase" "central-db" }} +{{ include "srox.configureCrypto" (list $ "central.db.serviceTLS" $centralDBCertSpec) }} +{{ end }} + +{{/* + Setup configuration for persistence backend. + TODO(ROX-16253): Remove PVC + */}} +{{ $volumeCfg := dict }} +{{ if $centralCfg.persistence.none }} + {{ $_ := set $volumeCfg "emptyDir" dict }} +{{ end }} +{{ if $centralCfg.persistence.hostPath }} + {{ if not $centralCfg.nodeSelector }} + {{ include "srox.warn" (list $ "You have selected host path persistence, but not specified a node selector. This is unlikely to work reliably.") }} + {{ end }} + {{ $_ := set $volumeCfg "hostPath" (dict "path" $centralCfg.persistence.hostPath) }} +{{ end }} +{{/* Configure PVC if either any of the settings in `central.persistence.persistentVolumeClaim` are provided, + or no other persistence backend has been configured yet. */}} +{{ if or (not (deepEqual $._rox._configShape.central.persistence.persistentVolumeClaim $centralCfg.persistence.persistentVolumeClaim)) (not $volumeCfg) }} + {{ $pvcCfg := $centralCfg.persistence.persistentVolumeClaim }} + {{ $_ := include "srox.mergeInto" (list $pvcCfg $._rox._defaults.pvcDefaults (dict "createClaim" $.Release.IsInstall)) }} + {{ $_ = set $volumeCfg "persistentVolumeClaim" (dict "claimName" $pvcCfg.claimName) }} + {{ if $pvcCfg.createClaim }} + {{ $_ = set $centralCfg.persistence "_pvcCfg" $pvcCfg }} + {{ end }} +{{ end }} + +{{/* + Central's DB PVC config setup + */}} +{{ $dbVolumeCfg := dict }} +{{ if not $centralDBCfg.external }} +{{ if $centralDBCfg.persistence.none }} + {{ include "srox.warn" (list $ "You have selected no persistence backend. Every deletion of the StackRox Central DB pod will cause you to lose all your data. This is STRONGLY recommended against.") }} + {{ $_ := set $dbVolumeCfg "emptyDir" dict }} +{{ end }} +{{ if $centralDBCfg.persistence.hostPath }} + {{ if not $centralDBCfg.nodeSelector }} + {{ include "srox.warn" (list $ "You have selected host path persistence, but not specified a node selector. This is unlikely to work reliably.") }} + {{ end }} + {{ $_ := set $dbVolumeCfg "hostPath" (dict "path" $centralDBCfg.persistence.hostPath) }} +{{ end }} +{{/* Configure PVC if either any of the settings in `centralDB.persistence.persistentVolumeClaim` are provided, + or no other persistence backend has been configured yet. */}} +{{ if or (not (deepEqual $._rox._configShape.central.db.persistence.persistentVolumeClaim $centralDBCfg.persistence.persistentVolumeClaim)) (not $dbVolumeCfg) }} + {{ $dbPVCCfg := $centralDBCfg.persistence.persistentVolumeClaim }} + {{ $_ := include "srox.mergeInto" (list $dbPVCCfg $._rox._defaults.dbPVCDefaults (dict "createClaim" (or .Release.IsInstall (eq $._rox._renderMode "centralDBOnly")))) }} + {{ $_ = set $dbVolumeCfg "persistentVolumeClaim" (dict "claimName" $dbPVCCfg.claimName) }} + {{ if $dbPVCCfg.createClaim }} + {{ $_ = set $centralDBCfg.persistence "_pvcCfg" $dbPVCCfg }} + {{ end }} +{{ end }} +{{ end }} + +{{ $allPersistenceMethods := keys $volumeCfg | sortAlpha }} +{{ if ne (len $allPersistenceMethods) 1 }} + {{ include "srox.fail" (printf "Invalid or no persistence configurations for central: [%s]" (join "," $allPersistenceMethods)) }} +{{ end }} +{{ $_ = set $centralCfg.persistence "_volumeCfg" $volumeCfg }} +{{ if not $centralDBCfg.external }} +{{ $_ = set $centralDBCfg.persistence "_volumeCfg" $dbVolumeCfg }} +{{ end }} + +{{/* Endpoint configuration */}} +{{ include "srox.configureCentralEndpoints" $._rox.central }} + +{{/* + Exposure configuration setup & sanity checks. + */}} +{{ if $._rox.central.exposure.loadBalancer.enabled }} + {{ include "srox.note" (list $ (printf "Exposing StackRox Central via LoadBalancer service.")) }} +{{ end }} +{{ if $._rox.central.exposure.nodePort.enabled }} + {{ include "srox.note" (list $ (printf "Exposing StackRox Central via NodePort service.")) }} +{{ end }} +{{ if $._rox.central.exposure.route.enabled }} + {{ if not $env.openshift }} + {{ include "srox.fail" (printf "The exposure method 'Route' is only available on OpenShift clusters.") }} + {{ end }} + {{ include "srox.note" (list $ (printf "Exposing StackRox Central via OpenShift Route https://central.%s." $.Release.Namespace)) }} +{{ end }} + +{{ if not (or $._rox.central.exposure.loadBalancer.enabled $._rox.central.exposure.nodePort.enabled $._rox.central.exposure.route.enabled) }} + {{ include "srox.note" (list $ "Not exposing StackRox Central, it will only be reachable cluster-internally.") }} + {{ include "srox.note" (list $ "To enable exposure via LoadBalancer service, use --set central.exposure.loadBalancer.enabled=true.") }} + {{ include "srox.note" (list $ "To enable exposure via NodePort service, use --set central.exposure.nodePort.enabled=true.") }} + {{ if $env.openshift }} + {{ include "srox.note" (list $ "To enable exposure via an OpenShift Route, use --set central.exposure.route.enabled=true.") }} + {{ end }} + {{ include "srox.note" (list $ (printf "To acccess StackRox Central via a port-forward on your local port 18443, run: kubectl -n %s port-forward svc/central 18443:443." .Release.Namespace)) }} +{{ end }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_crypto.tpl b/rhacs/4.3.8/central-services/templates/_crypto.tpl new file mode 100644 index 0000000..1455288 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_crypto.tpl @@ -0,0 +1,239 @@ +{{/* + srox.configureCrypto $ $cryptoConfigPath $spec + + This helper function configures a private key or certificate (public cert + private key) + config entry, from an input config which is accessed via $cryptoConfigPath relative to + $._rox, which we'll refer to as $inputCfg. $inputCfg is expected to be a dict with at + least `key` and `generate` properties. If `generate` is null, it defaults to either `true` + on installations, and `false` on upgrades. `key` is an expandable string. + The result in either mode is written to a dict $outputCfg under $._rox accessed by the + $cryptoConfigPath, with a '_' prepended to the last path element. E.g., if + $cryptoConfigPath is "a.b.c", the input configuration will be read from $._rox.a.b.c, and + the output configuration will be stored in $._rox.a.b._c. + + Private key-only mode is selected if $spec.keyOnly contains a non-zero string, which specifies + the key algorithm to use. In this mode, if $inputCfg.key expands to a non-empty string, this + string will be copied to the `Key` property of $outputCfg. Otherwise, if $inputCfg.generate + is true (wrt. the above defaulting rules), a key with the algorithm prescribed by $spec.keyOnly + will be generated and stored in the `Key` property of $outputCfg. + + Certificate mode is the default. If $inputCfg.cert and $inputCfg.key expand to non-empty strings, + these strings will be copied to the `Cert` and `Key` properties of $outputCfg. Otherwise, if both + of them expand to empty strings (it is an error if only one of them expands to a non-empty + string), and $inputCfg.generate is true, a certificate and private key are generated with the + following options: + - If $inputCfg.ca is true, generate a CA certificate with common name $inputCfg.CN and a 5 year + validity duration. + - Otherwise, generate a leaf certificate with common name $inputCfg.CN and a 1 year validity + duration. The SANs for this certificate are derived from the base DNS name $inputCfg.dnsBase + according to "srox.computeSANs". + + Whenever certificates and/or private keys were generated, the $._rox._state.generated property + is updated to reflect the generated values, such that merging $._rox._state.generated in to + $.Values would have caused this template to simply use the generated values as-is. E.g., if + $cryptoConfigPath was "a.b.c" and $.Values.a.b.c.cert" and $.Values.a.b.c.key" were both empty, + $._rox._state.generated.a.b.c would be set to be a dict with `cert` and `key` properties of the + generated $outputCfg.Cert and $outputCfg.Key. + + If a certificate or private key was generated, $._rox._state.customCertGen is set to true. + */}} +{{- define "srox.configureCrypto" -}} +{{ $ := index . 0 }} +{{ $cryptoConfigPath := index . 1 }} +{{ $spec := index . 2 }} + +{{/* Resolve $cryptoConfigPath. */}} +{{ $cfg := $._rox }} +{{ $newGenerated := dict }} +{{ $genCfg := $newGenerated }} +{{ $cryptoConfigPathList := splitList "." $cryptoConfigPath }} +{{ range $pathElem := $cryptoConfigPathList }} + {{ $cfg = index $cfg $pathElem }} + {{ $newCfg := dict }} + {{ $_ := set $genCfg $pathElem $newCfg }} + {{ $genCfg = $newCfg }} +{{ end }} + +{{/* Make sure `cert` and `key` are expanded (this should already be the case, but better + safe than sorry. */}} +{{ $certExpandSpec := dict "cert" true "key" true }} +{{ include "srox.expandAll" (list $ $cfg $certExpandSpec $cryptoConfigPathList) }} + +{{ $certPEM := $cfg._cert }} +{{ $keyPEM := $cfg._key }} + +{{ $result := dict }} +{{ if $certPEM }} + {{ $result = dict "Cert" $certPEM "Key" (default "" $keyPEM) }} +{{ else if or $certPEM $keyPEM }} + {{ if and $keyPEM $spec.keyOnly }} + {{ $_ := set $result "Key" $keyPEM }} + {{ else }} + {{ include "srox.fail" (printf "Either none or both of %s.cert and %s.key must be specified" $cryptoConfigPath $cryptoConfigPath) }} + {{ end }} +{{ else }} + {{ $generate := $cfg.generate }} + {{ if kindIs "invalid" $generate }} + {{ $generate = $.Release.IsInstall }} + {{ end }} + {{ if $generate }} + {{ if $spec.ca }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"ca\" (genCA .cn 1825) }}" (dict "Template" $.Template "cn" $spec.CN "out" $out) }} + {{ $result = $out.ca }} + {{ else if $spec.keyOnly }} + {{ $key := tpl "{{ genPrivateKey .algo }}" (dict "Template" $.Template "algo" $spec.keyOnly) }} + {{ $_ := set $genCfg "key" $key }} + {{ $_ = set $result "Key" $key }} + {{ else }} + {{ if not $._rox._ca }} + {{ include "srox.fail" (printf "Tried to generate certificate for %s, but no CA certificate is available." $spec.CN) }} + {{ end }} + {{ $sans := dict }} + {{ include "srox.computeSANs" (list $ $sans $spec.dnsBase) }} + {{ $ca := $._rox._ca }} + {{ if kindIs "map" $ca }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"ca\" (buildCustomCert (b64enc .ca.Cert) (b64enc .ca.Key)) }}" (dict "Template" $.Template "ca" $ca "out" $out) }} + {{ $ca = $out.ca }} + {{ end }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"cert\" (genSignedCert .cn nil .sans 365 .ca) }}" (dict "Template" $.Template "cn" $spec.CN "sans" $sans.result "ca" $ca "out" $out) }} + {{ $result = $out.cert }} + {{ $_ := set $genCfg "cert" $result.Cert }} + {{ $_ = set $genCfg "key" $result.Key }} + {{ end }} + {{ $_ := set $genCfg "key" $result.Key }} + {{ if $result.Cert }} + {{ $_ = set $genCfg "cert" $result.Cert }} + {{ end }} + {{ $_ = set $._rox._state "customCertGen" true }} + {{ end }} +{{ end }} + +{{/* Store output configuration and generated properties */}} +{{ $newCfgRoot := dict }} +{{ $newCfg := $newCfgRoot }} +{{ range $pathElem := initial $cryptoConfigPathList }} + {{ $nextCfg := dict }} + {{ $_ := set $newCfg $pathElem $nextCfg }} + {{ $newCfg = $nextCfg }} +{{ end }} +{{ $_ := set $newCfg (last $cryptoConfigPathList | printf "_%s") $result }} +{{ $_ = include "srox.mergeInto" (list $._rox $newCfgRoot) }} +{{ $_ = include "srox.mergeInto" (list $._rox._state.generated $newGenerated) }} +{{ end }} + + +{{/* + srox.configurePassword $ $pwConfigPath [$htpasswdUser] + + This helper function reads a password configuration (YAML dict with `value` + and `generate` properties) referenced by $pwConfigPath relative to $._rox. It + ensures the dict with the same config path relative to $._rox and prepending an underscore + to the last path element is populated in the following way: + - If the `value` property of the input config is nonzero, set `value` in the result to the + expanded value. + - If the optional $htpasswdUser parameter is specified and the `htpasswd` property of the + input config is nonzero, set `htpasswd` in the result to the expanded value of that + property. + - If none of the above (non-mutually-exclusive) cases apply: + - If `generate` is true OR both `generate` is null and this is an installation, + not an upgrade, generate a random password with 32 alphanumeric characters. + - Otherwise, leave the result property empty. + - If the optional $htpasswdUser parameter was specified AND the `value` property in the + result property was set per the above rules AND the `htpasswd` property was not set, + populate the `htpasswd` property of the result by generating an htpasswd stanza with + the computed `value` as the password and $htpasswdUser as the username. + + The $._rox._state.generated property is adjusted accordingly. + */}} +{{- define "srox.configurePassword" -}} +{{ $ := index . 0 }} +{{ $pwConfigPath := index . 1 }} +{{ $htpasswdUser := "" }} +{{ if gt (len .) 2 }} + {{ $htpasswdUser = index . 2 }} +{{ end }} +{{ $cfg := $._rox }} +{{ $newGenerated := dict }} +{{ $genCfg := $newGenerated }} +{{ $pwConfigPathList := splitList "." $pwConfigPath }} +{{ range $pathElem := $pwConfigPathList }} + {{ $cfg = index $cfg $pathElem }} + {{ $newCfg := dict }} + {{ $_ := set $genCfg $pathElem $newCfg }} + {{ $genCfg = $newCfg }} +{{ end }} + +{{/* Make sure that `value` and `htpasswd` within $cfg are expanded (this should already be the + case but better safe than sorry). */}} +{{ $pwExpandSpec := dict "value" true "htpasswd" true }} +{{ include "srox.expandAll" (list $ $cfg $pwExpandSpec $pwConfigPathList) }} + +{{ $result := dict }} +{{ if and $htpasswdUser (not (kindIs "invalid" $cfg._htpasswd)) }} + {{ $htpasswd := $cfg._htpasswd }} + {{ $_ := set $result "htpasswd" $htpasswd }} +{{ end }} +{{ if not $result.htpasswd }} + {{ $pw := dict.nil }} + {{ if kindIs "invalid" $cfg._value }} + {{ $generate := $cfg.generate }} + {{ if kindIs "invalid" $generate }} + {{ $generate = $.Release.IsInstall }} + {{ end }} + {{ if $generate }} + {{ $pw = randAlphaNum 32 }} + {{ $_ := set $genCfg "value" $pw }} + {{ end }} + {{ else }} + {{ $pw = $cfg._value }} + {{ end }} + {{ if not (kindIs "invalid" $pw) }} + {{ $_ := set $result "value" $pw }} + {{ end }} + {{ if and $htpasswdUser $pw }} + {{ $htpasswd := tpl "{{ htpasswd .user .pw }}" (dict "Template" $.Template "user" $htpasswdUser "pw" $pw) }} + {{ $_ := set $result "htpasswd" $htpasswd }} + {{ end }} +{{ else if $cfg.value }} + {{ include "srox.fail" (printf "Both a htpasswd and a value are specified for %s, this is illegal. Remove the `value` property, or ensure that `htpasswd` is null." $pwConfigPath) }} +{{ end }} +{{ $newCfgRoot := dict }} +{{ $newCfg := $newCfgRoot }} +{{ range $pathElem := initial $pwConfigPathList }} + {{ $nextCfg := dict }} + {{ $_ := set $newCfg $pathElem $nextCfg }} + {{ $newCfg = $nextCfg }} +{{ end }} +{{ $_ := set $newCfg (last $pwConfigPathList | printf "_%s") $result }} +{{ $_ = include "srox.mergeInto" (list $._rox $newCfgRoot) }} +{{ $_ = include "srox.mergeInto" (list $._rox._state.generated $newGenerated) }} +{{ end }} + + +{{/* + srox.computeSANs $ $out $svcName + + Compute the applicable SANs for a service with name $svcName, deployed in namespace + $.Release.Namespace (= $releaseNS). + Generally, SANs following the pattern "$svcName.$releaseNS[.svc[.cluster.local]]" will be + generated. If $releaseNS is not "stackrox", another set of SANs with the same pattern, + but assuming $releaseNS = "stackrox", will be generated in addition. + The result is stored as a list in $out.result. + */}} +{{ define "srox.computeSANs" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ $svcName := index . 2 }} +{{ $releaseNS := $.Release.Namespace }} +{{ $sans := list }} +{{ range $ns := list $releaseNS "stackrox" | uniq | sortAlpha }} + {{ $baseDNS := printf "%s.%s" $svcName $ns }} + {{ range $suffix := tuple "" ".svc" ".svc.cluster.local" }} + {{ $sans = printf "%s%s" $baseDNS $suffix | append $sans }} + {{ end }} +{{ end }} +{{ $_ := set $out "result" $sans }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_dict.tpl b/rhacs/4.3.8/central-services/templates/_dict.tpl new file mode 100644 index 0000000..bf14a6d --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_dict.tpl @@ -0,0 +1,142 @@ +{{/* + srox.compactDict $target [$depth] + + Compacts a dict $target by removing entries with empty values. + By default, only the top-level dict $target itself is modified. If the optional $depth + parameter is specified and is non-zero, this determines the recursion depth over which the + compaction is applied to nested diocts as well. A $depth of -1 means to compact all nested + dicts, regardless of depth. + */}} +{{ define "srox.compactDict" }} +{{ $args := . }} +{{ if not (kindIs "slice" $args) }} + {{ $args = list $args 0 }} +{{ end }} +{{ $target := index $args 0 }} +{{ $depth := index $args 1 }} +{{ $zeroValKeys := list }} +{{ range $k, $v := $target }} + {{ if and (kindIs "map" $v) (ne $depth 0) }} + {{ include "srox.compactDict" (list $v (sub $depth 1)) }} + {{ end }} + {{ if not $v }} + {{ $zeroValKeys = append $zeroValKeys $k }} + {{ end }} +{{ end }} +{{ range $k := $zeroValKeys }} + {{ $_ := unset $target $k }} +{{ end }} +{{ end }} + +{{/* + srox.destructiveMergeOverwrite $out $dict1 $dict2... + + Recursively merges $dict1, $dict2 (in this order) into $out, similar to mergeOverwrite. + The eponymous difference is the fact that any explicit "null" entries in the source + dictionaries cause the respective entry to be deleted. + */}} +{{ define "srox.destructiveMergeOverwrite" }} +{{ $out := first . }} +{{ $toMergeList := rest . }} +{{ range $toMerge := $toMergeList }} + {{ range $k, $v := $toMerge }} + {{ if kindIs "invalid" $v }} + {{ $_ := unset $out $k }} + {{ else if kindIs "map" $v }} + {{ $outV := index $out $k }} + {{ if kindIs "invalid" $outV }} + {{ $_ := set $out $k (deepCopy $v) }} + {{ else if kindIs "map" $outV }} + {{ include "srox.destructiveMergeOverwrite" (list $outV $v) }} + {{ else }} + {{ fail (printf "when merging at key %s: incompatible kinds %s and %s" $k (kindOf $v) (kindOf $outV)) }} + {{ end }} + {{ else }} + {{ $_ := set $out $k $v }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox.stringifyDictValues $dict + + Recursively traverses $dict and converts every non-dict value to a string. + */}} +{{ define "srox.stringifyDictValues" }} +{{ $dict := . }} +{{ range $k, $v := $dict }} + {{ if kindIs "map" $v }} + {{ include "srox.stringifyDictValues" $v }} + {{ else }} + {{ $_ := set $dict $k (toString $v) }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox.safeDictLookup $dict $out $path + + Looks up $path in $dict, and stores the result (if any) in $out.result. + $path is a dot-separated list of nested field names. An empty $path causes + $dict to be stored in $out.result. + + Example: srox.safeDictLookup $dict $out "a.b.c" stores the value of $dict.a.b.c, if + it exists, in $out.result. Otherwise, it does nothing - in particular, it does + not fail, as accessing $dict.a.b.c unconditionally would if any of $dict, $dict.a, + or $dict.a.b was not a dict. + */}} +{{ define "srox.safeDictLookup" }} +{{ $dict := index . 0 }} +{{ $out := index . 1 }} +{{ $path := index . 2 }} +{{ $curr := $dict }} +{{ $pathList := splitList "." $path | compact }} +{{ range $pathElem := $pathList }} + {{ if kindIs "map" $curr }} + {{ $curr = index $curr $pathElem }} + {{ else if not (kindIs "invalid" $curr) }} + {{ $curr = dict.nil }} + {{ end }} +{{ end }} +{{ if not (kindIs "invalid" $curr) }} + {{ $_ := set $out "result" $curr }} +{{ end }} +{{ end }} + + + +{{/* + srox.mergeInto $tgt $src1..$srcN + + Recursively merges values from $src1, ..., $srcN into $tgt, giving preference to + values in $tgt. + + Unlike Sprig's merge, this does not overwrite falsy values when explicitly defined, + with the exception of `null` values (this also sets it apart from Sprig's mergeOverwrite). + + Whenever entire (nested) dicts are merged as-is from one of the sources into $tgt, a deep + copy of the respective nested dict is created. + + An empty string is always returned, hence this should be invoked in the form + $_ := include "srox.mergeInto" (list $tgt $src1 $src2) + */}} +{{ define "srox.mergeInto" }} +{{ $tgt := first . }} +{{ range $src := rest . }} + {{ range $k, $srcV := $src }} + {{ $tgtV := index $tgt $k }} + {{ if kindIs "map" $srcV }} + {{ if kindIs "invalid" $tgtV }} + {{ $_ := set $tgt $k (deepCopy $srcV) }} + {{ else if kindIs "map" $tgtV }} + {{ $_ := include "srox.mergeInto" (list $tgtV $srcV) }} + {{ else }} + {{ fail (printf "Incompatible kinds for key %s: %s vs %s" $k (kindOf $srcV) (kindOf $tgtV)) }} + {{ end }} + {{ else if and (not (kindIs "invalid" $srcV)) (kindIs "invalid" $tgtV) }} + {{ $_ := set $tgt $k $srcV }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_expand.tpl b/rhacs/4.3.8/central-services/templates/_expand.tpl new file mode 100644 index 0000000..ed1cb1f --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_expand.tpl @@ -0,0 +1,96 @@ +{{/* + srox.expandAll $ $target $expandable [$path] + + Expands values within $target that are flagged in $expandable, using $path + as the path from the configuration root to $target for error reporting purposes. + + If $target is nil, nothing happens. Otherwise, $target must be a dict. For every key + of $target that is also present in $expandable, the following action is performed: + - If the entry in $expandable is a dict, recursive invoke "srox.expandAll" on the + respective entries, with an adjusted $path. + - Otherwise, the entry in $expandable is assume to be of boolean value. If the value is + true, the corresponding entry's value in $target is expanded (see "srox._expandSingle" + below for a definition of expanding), and the result of the expansion is stored under + the key with a "_" prepended in $target. The original entry in $target is removed. This + ensures "srox.expandAll" is an idempotent operation). + */}} +{{ define "srox.expandAll" }} +{{ $args := . }} +{{ $ := index $args 0 }} +{{ $target := index $args 1 }} +{{ $expandable := index $args 2 }} +{{ $path := list }} +{{ if ge (len $args) 4 }} + {{ $path = index $args 3 }} + {{ if kindIs "string" $path }} + {{ $path = splitList "." $path | compact }} + {{ end }} +{{ end }} + +{{ if kindIs "map" $target }} + {{ range $k, $v := $expandable }} + {{ $childPath := append $path $k }} + {{ $targetV := index $target $k }} + {{ if kindIs "map" $v }} + {{ include "srox.expandAll" (list $ $targetV $v $childPath) }} + {{ else if $v }} + {{ if not (kindIs "invalid" $targetV) }} + {{ $expanded := include "srox._expandSingle" (list $ $targetV (join "." $childPath)) }} + {{ $_ := set $target (printf "_%s" $k) $expanded }} + {{ end }} + {{ $_ := unset $target $k }} + {{ end }} + {{ end }} +{{ else if not (kindIs "invalid" $target) }} + {{ include "srox.fail" (printf "Error expanding value at %s: expected map, got: %s" (join "." $path) (kindOf $target)) }} +{{ end }} +{{ end }} + +{{/* + srox.expand $ $spec + + Parses and expands a "specification string" in the following way: + - If $spec is a dictionary, return $spec rendered as a YAML. + - Otherwise, if $spec starts with a backslash character (`\`), return $spec minus the leading + backslash character. + - Otherwise, if $spec starts with an `@` character, strip off the first character and + treat the remainder of the string as a `|`-separated list of file names. Try to load + each referenced file, in order, via `stackrox.getFile`. The result is the first file + that could be successfully loaded. If no file could be loaded, expansion fails. + - Otherwise, return $spec as-is. + */}} +{{- define "srox._expandSingle" -}} + {{- $ := index . 0 -}} + {{- $spec := index . 1 -}} + {{- $context := index . 2 -}} + {{- $result := "" -}} + {{- if kindIs "string" $spec -}} + {{- if hasPrefix "\\" $spec -}} + {{- /* use \ as string-wide escape character */ -}} + {{- $result = trimPrefix "\\" $spec -}} + {{- else if hasPrefix "@" $spec -}} + {{- /* treat as file list (first found matches) */ -}} + {{- /* If the prefix is "@?" expansion will not fail if no files could be found, instead an empty string is returned. */ -}} + {{- $fileSpec := trimPrefix "@" $spec -}} + {{- $allowNotFound := false -}} + {{- if hasPrefix "?" $fileSpec -}} + {{- $allowNotFound = true -}} + {{- $fileSpec = trimPrefix "?" $fileSpec -}} + {{- end -}} + {{- $fileList := regexSplit "\\s*\\|\\s*" ($fileSpec | trim) -1 -}} + {{- $fileRes := dict -}} + {{- $_ := include "srox.loadFile" (list $ $fileRes $fileList) -}} + {{- if and (not $allowNotFound) (not $fileRes.found) -}} + {{- include "srox.fail" (printf "Expanding %s: file reference %q: none of the referenced files were found" $context $spec) -}} + {{- end -}} + {{- $result = default "" $fileRes.contents -}} + {{- else -}} + {{/* treat as raw string */}} + {{- $result = $spec -}} + {{- end -}} + {{- else if not (kindIs "invalid" $spec) -}} + {{- /* render non-string, non-nil values as YAML */ -}} + {{- $result = toYaml $spec -}} + {{- end -}} + {{- $result -}} +{{- end -}} diff --git a/rhacs/4.3.8/central-services/templates/_format.tpl b/rhacs/4.3.8/central-services/templates/_format.tpl new file mode 100644 index 0000000..745fe47 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_format.tpl @@ -0,0 +1,14 @@ +{{/* + srox.formatStorageSize $value + + Formats $value as a storage size. $value can be an integer or a string. + If no unit is specified (e.g., if $value is a string), a default unit of + Gigabytes ("Gi" suffix) is assumed. + */}} +{{- define "srox.formatStorageSize" -}} +{{- $val := toString . -}} +{{- if regexMatch "^[0-9]+$" $val -}} + {{- $val = printf "%sGi" $val -}} +{{- end -}} +{{- default "0" $val -}} +{{- end -}} diff --git a/rhacs/4.3.8/central-services/templates/_helpers.tpl b/rhacs/4.3.8/central-services/templates/_helpers.tpl new file mode 100644 index 0000000..e87f10f --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_helpers.tpl @@ -0,0 +1,68 @@ +{{/* + Misceallaneous helper templates. + */}} + + + + +{{/* + srox.loadFile $ $out $fileName-or-list + + This helper function reads a file. It differs from $.Files.Get in that it also takes + $._rox.meta.fileOverrides into account. Furthermore, it can receive a list of file names, + and will try these files in order. Finally, it indicates whether a file was found via the + $out.found property (as opposed to $.Files.Get, which cannot distinguish between a successful + read of an empty file, and this file not being found). + The file contents will be returned via $out.contents + */}} +{{ define "srox.loadFile" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ $fileNames := index . 2 }} +{{ if not (kindIs "slice" $fileNames) }} + {{ $fileNames = list $fileNames }} +{{ end }} +{{ $contents := index dict "" }} +{{ range $fileName := $fileNames }} + {{ if kindIs "invalid" $contents }} + {{ $contents = index $._rox.meta.fileOverrides $fileName }} + {{ end }} + {{ if kindIs "invalid" $contents }} + {{ range $path, $_ := $.Files.Glob $fileName }} + {{ if kindIs "invalid" $contents }} + {{ $contents = $.Files.Get $path }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ if not (kindIs "invalid" $contents) }} + {{ $_ := set $out "contents" $contents }} +{{ end }} +{{ $_ := set $out "found" (not (kindIs "invalid" $contents)) }} +{{ end }} + + +{{/* + srox.checkGenerated $ $cfgPath + + Checks if the value at configuration path $cfgPath (e.g., "central.adminPassword.value") was + generated. Evaluates to the string "true" if this is the case, and an empty string otherwise. + */}} +{{- define "srox.checkGenerated" -}} +{{- $ := index . 0 -}} +{{- $cfgPath := index . 1 -}} +{{- $genCfg := $._rox._state.generated -}} +{{- $exists := true -}} +{{- range $pathElem := splitList "." $cfgPath -}} + {{- if $exists -}} + {{- if hasKey $genCfg $pathElem -}} + {{- $genCfg = index $genCfg $pathElem -}} + {{- else -}} + {{- $exists = false -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $exists -}} +true +{{- end -}} +{{- end -}} diff --git a/rhacs/4.3.8/central-services/templates/_image-pull-secrets.tpl b/rhacs/4.3.8/central-services/templates/_image-pull-secrets.tpl new file mode 100644 index 0000000..9747e26 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_image-pull-secrets.tpl @@ -0,0 +1,85 @@ +{{/* + srox.configureImagePullSecrets $ $cfgName $imagePullSecrets $secretResourceName $defaultSecretNames $namespace + + Configures image pull secrets. + + This function enriches $imagePullSecrets based on the exposed configuration parameters to contain + a list of Kubernetes secret names as `_names` to be used as image pull secrets within the chart + templates. This list contains the following secrets: + + - Secrets referenced via $imagePullSecrets.useExisting. + - Image pull secrets associated with the default service account (if + $imagePullSecrets.useFromDefaultServiceAccount is true). + - $secretResourceName, if $imagePullSecrets.username is set. + - $defaultSecretNames. */}} + +{{ define "srox.configureImagePullSecrets" }} +{{ $ := index . 0 }} +{{ $cfgName := index . 1 }} +{{ $imagePullSecrets := index . 2 }} +{{ $secretResourceName := index . 3 }} +{{ $defaultSecretNames := index . 4 }} +{{ $namespace := index . 5 }} + +{{ $imagePullSecretNames := default list $imagePullSecrets.useExisting }} +{{ if not (kindIs "slice" $imagePullSecretNames) }} + {{ $imagePullSecretNames = regexSplit "\\s*[,;]\\s*" (trim $imagePullSecretNames) -1 }} +{{ end }} +{{ if $imagePullSecrets.useFromDefaultServiceAccount }} + {{ $defaultSA := dict }} + {{ include "srox.safeLookup" (list $ $defaultSA "v1" "ServiceAccount" $namespace "default") }} + {{ if $defaultSA.result }} + {{ range $ips := default list $defaultSA.result.imagePullSecrets }} + {{ if $ips.name }} + {{ $imagePullSecretNames = append $imagePullSecretNames $ips.name }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ $imagePullCreds := dict }} +{{ if $imagePullSecrets._username }} + {{ $imagePullCreds = dict "username" $imagePullSecrets._username "password" $imagePullSecrets._password }} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretResourceName }} +{{ else if $imagePullSecrets._password }} + {{ $msg := printf "Username missing in %q. Whenever an image pull password is specified, a username must be specified as well" $cfgName }} + {{ include "srox.fail" $msg }} +{{ end }} +{{ if and $.Release.IsInstall (not $imagePullSecretNames) (not $imagePullSecrets.allowNone) }} + {{ $msg := printf "You have not specified any image pull secrets, and no existing image pull secrets were automatically inferred. If your registry does not need image pull credentials, explicitly set the '%s.allowNone' option to 'true'" $cfgName }} + {{ include "srox.fail" $msg }} +{{ end }} + +{{ $imagePullSecretNames = concat (append $imagePullSecretNames $secretResourceName) $defaultSecretNames | uniq | sortAlpha }} +{{ $_ := set $imagePullSecrets "_names" $imagePullSecretNames }} +{{ $_ := set $imagePullSecrets "_creds" $imagePullCreds }} + +{{ end }} + +{{ define "srox.configureImagePullSecretsForDockerRegistry" }} +{{ $ := index . 0 }} +{{ $imagePullSecrets := index . 1 }} + +{{/* Setup Image Pull Secrets for Docker Registry. + Note: This must happen afterwards, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} +{{ if $imagePullSecrets._username }} + {{ $dockerAuths := dict }} + {{ range $image := keys $._rox._state.referencedImages }} + {{ $registry := splitList "/" $image | first }} + {{ if eq $registry "docker.io" }} + {{/* Special case docker.io */}} + {{ $registry = "https://index.docker.io/v1/" }} + {{ else }} + {{ $registry = printf "https://%s" $registry }} + {{ end }} + {{ $_ := set $dockerAuths $registry dict }} + {{ end }} + {{ $authToken := printf "%s:%s" $imagePullSecrets._username $imagePullSecrets._password | b64enc }} + {{ range $regSettings := values $dockerAuths }} + {{ $_ := set $regSettings "auth" $authToken }} + {{ end }} + + {{ $_ := set $imagePullSecrets "_dockerAuths" $dockerAuths }} +{{ end }} + +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_images.tpl b/rhacs/4.3.8/central-services/templates/_images.tpl new file mode 100644 index 0000000..dced29d --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_images.tpl @@ -0,0 +1,34 @@ +{{/* + srox.configureImage $ $imageCfg + + Configures settings for a single image by augmenting/completing an existing image configuration + stanza. + + If $imageCfg.fullRef is empty: + First, the image registry is determined by inspecting $imageCfg.registry and, if this is empty, + $._rox.image.registry, ultimately defaulting to `docker.io`. The full image ref is then + constructed from the registry, $imageCfg.name (must be non-empty), and $imageCfg.tag (may be + empty, in which case "latest" is assumed). The result is stored in $imageCfg.fullRef. + + Afterwards (irrespective of the previous check), $imageCfg.fullRef is modified by prepending + "docker.io/" if and only if it did not contain a remote yet (i.e., the part before the first "/" + did not contain a dot (DNS name) or colon (port)). + + Finally, the resulting $imageCfg.fullRef is stored as a dict entry with value `true` in the + $._rox._state.referencedImages dict. + */}} +{{ define "srox.configureImage" }} +{{ $ := index . 0 }} +{{ $imageCfg := index . 1 }} +{{ $imageRef := $imageCfg.fullRef }} +{{ if not $imageRef }} + {{ $imageRef = printf "%s/%s:%s" (coalesce $imageCfg.registry $._rox.image.registry "docker.io") $imageCfg.name (default "latest" $imageCfg.tag) }} +{{ end }} +{{ $imageComponents := splitList "/" $imageRef }} +{{ $firstComponent := index $imageComponents 0 }} +{{ if or (lt (len $imageComponents) 2) (and (not (contains ":" $firstComponent)) (not (contains "." $firstComponent))) }} + {{ $imageRef = printf "docker.io/%s" $imageRef }} +{{ end }} +{{ $_ := set $imageCfg "fullRef" $imageRef }} +{{ $_ = set $._rox._state.referencedImages $imageRef true }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_init.tpl b/rhacs/4.3.8/central-services/templates/_init.tpl new file mode 100644 index 0000000..6708058 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_init.tpl @@ -0,0 +1,285 @@ +{{/* + srox.init $ + + Initialization template for the internal data structures. + This template is designed to be included in every template file, but will only be executed + once by leveraging state sharing between templates. + */}} +{{ define "srox.init" }} + +{{ $ := . }} + +{{/* + On first(!) instantiation, set up the $._rox structure, containing everything required by + the resource template files. + */}} +{{ if not $._rox }} + +{{/* + Initial Setup + */}} + +{{/* + $rox / ._rox is the dictionary in which _all_ data that is modified by the init logic + is stored. + We ensure that it has the required shape, and then right after merging the user-specified + $.Values, we apply some bootstrap defaults. + */}} +{{ $rox := deepCopy $.Values }} +{{ $_ := set $ "_rox" $rox }} + +{{/* Global state (accessed from sub-templates) */}} +{{ $generatedName := printf "stackrox-generated-%s" (randAlphaNum 6 | lower) }} +{{ $state := dict "customCertGen" false "generated" dict "generatedName" $generatedName "notes" list "warnings" list "referencedImages" dict }} +{{ $_ = set $._rox "_state" $state }} + +{{ $configShape := $.Files.Get "internal/config-shape.yaml" | fromYaml }} +{{ $configShapeScanner := $.Files.Get "internal/scanner-config-shape.yaml" | fromYaml}} + +{{ $_ = include "srox.mergeInto" (list $rox $configShape $configShapeScanner (tpl ($.Files.Get "internal/bootstrap-defaults.yaml.tpl") . | fromYaml)) }} +{{ $_ = set $._rox "_configShape" $configShape }} + +{{/* + General validation. + */}} +{{ if ne $.Release.Namespace "stackrox" }} + {{ if $._rox.allowNonstandardNamespace }} + {{ include "srox.note" (list $ (printf "You have chosen to deploy to namespace '%s'." $.Release.Namespace)) }} + {{ else }} + {{ include "srox.fail" (printf "You have chosen to deploy to namespace '%s', not 'stackrox'. If this was accidental, please re-run helm with the '-n stackrox' option. Otherwise, if you need to deploy into this namespace, set the 'allowNonstandardNamespace' configuration value to true." $.Release.Namespace) }} + {{ end }} +{{ end }} + +{{ if ne $.Release.Name $.Chart.Name }} + {{ if $._rox.allowNonstandardReleaseName }} + {{ include "srox.warn" (list $ (printf "You have chosen a release name of '%s', not '%s'. Accompanying scripts and commands in documentation might require adjustments." $.Release.Name $.Chart.Name)) }} + {{ else }} + {{ include "srox.fail" (printf "You have chosen a release name of '%s', not '%s'. We strongly recommend using the standard release name. If you must use a different name, set the 'allowNonstandardReleaseName' configuration option to true." $.Release.Name $.Chart.Name) }} + {{ end }} +{{ end }} + + +{{ if and $.Release.IsInstall (not ._rox.central.persistence.none)}} + {{ include "srox.fail" (printf "Starting from 4.1, we stop creating central PVC during installation. Databases and persistent data are stored in Central DB or external databases. You may use `--set central.persistence.none=true` during Helm install to override default persistence config. Got %v" $._rox.central.persistence) }} +{{ end }} + + +{{ if $._rox.central.db.external }} + {{ if not $._rox.central.db.source.connectionString }} + {{ include "srox.warn" (list $ "You have chosen to bring your own Central DB without providing its connection string. We are using the default source string. To ensure the connection to your Central DB, you may override it with `--set central.db.source.connectionString=`.") }} + {{ end }} + {{ if not $._rox.central.db.password.value }} + {{ include "srox.warn" (list $ "You have chosen to bring your own Central DB without providing its password. We are using a generated password for now. To ensure the connection to your Central DB, you may provide your DB password by `--set central.db.password.value=`.") }} + {{ end }} +{{ end }} + +{{/* Initialize global prefix */}} +{{- include "srox.initGlobalPrefix" (list $) -}} + +{{/* + API Server setup. The problem with `.Capabilities.APIVersions` is that Helm does not + allow setting overrides for those when using `helm template` or `--dry-run`. Thus, + if we rely on `.Capabilities.APIVersions` directly, we lose flexibility for our chart + in these settings. Therefore, we use custom fields such that a user in principle has + the option to inject via `--set`/`-f` everything we rely upon. + */}} +{{ $apiResources := list }} +{{ if not (kindIs "invalid" $._rox.meta.apiServer.overrideAPIResources) }} + {{ $apiResources = $._rox.meta.apiServer.overrideAPIResources }} +{{ else }} + {{ range $apiResource := $.Capabilities.APIVersions }} + {{ $apiResources = append $apiResources $apiResource }} + {{ end }} +{{ end }} +{{ if $._rox.meta.apiServer.extraAPIResources }} + {{ $apiResources = concat $apiResources $._rox.meta.apiServer.extraAPIResources }} +{{ end }} +{{ $apiServerVersion := coalesce $._rox.meta.apiServer.version $.Capabilities.KubeVersion.Version }} +{{ $apiServer := dict "apiResources" $apiResources "version" $apiServerVersion }} +{{ $_ = set $._rox "_apiServer" $apiServer }} + +{{/* + Environment setup - part 1 + */}} +{{ $env := $._rox.env }} + +{{/* Detect openshift version */}} +{{ include "srox.autoSenseOpenshiftVersion" (list $) }} + +{{/* Openshift monitoring */}} +{{ if $._rox.enableOpenShiftMonitoring }} + {{ include "srox.warn" (list . "enableOpenShiftMonitoring option was replaced with monitoring.openshift.enabled") }} + {{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" true)) }} +{{ end }} +{{/* Default `monitoring.openshift.enabled = true` unless `env.openshift != 4`. */}} +{{ if kindIs "invalid" $._rox.monitoring.openshift.enabled }} +{{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" (eq $._rox.env.openshift 4))) }} +{{ end }} +{{ if and $._rox.monitoring.openshift.enabled (ne $._rox.env.openshift 4) }} + {{ include "srox.warn" (list . "'monitoring.openshift.enabled' is set to true, but the chart is not being deployed in an OpenShift 4 cluster. Proceeding with 'monitoring.openshift.enabled=false'.") }} + {{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" false)) }} +{{ end }} +{{ if $._rox.monitoring.openshift.enabled }} + {{ $_ := set $._rox.central "monitoring" dict }} + {{ include "srox.mergeInto" (list $._rox.central.monitoring $._rox.monitoring) }} +{{ end }} + +{{/* Infer GKE, if needed */}} +{{ if kindIs "invalid" $env.platform }} + {{ $platform := "default" }} + {{ if contains "-gke." $._rox._apiServer.version }} + {{ include "srox.note" (list $ "Based on API server properties, we have inferred that you are deploying into a GKE cluster. Set the `env.platform` property to a concrete value to override the auto-sensed value.") }} + {{ $platform = "gke" }} + {{ end }} + {{ $_ := set $env "platform" $platform }} +{{ end }} +{{/* Detect enablePodSecurityPolicies */}} +{{ include "srox.autoSensePodSecurityPolicies" (list $) }} + + +{{ $_ := set $env "installMethod" "helm" }} + + +{{/* Apply defaults */}} +{{ $defaultsCfg := dict }} +{{ $platformCfgFile := dict }} +{{ include "srox.loadFile" (list $ $platformCfgFile (printf "internal/platforms/%s.yaml" $env.platform)) }} +{{ if not $platformCfgFile.found }} + {{ include "srox.fail" (printf "Invalid platform %q. Please select a valid platform, or leave this field unset." $env.platform) }} +{{ end }} +{{ $_ = include "srox.mergeInto" (list $defaultsCfg (fromYaml $platformCfgFile.contents) ($.Files.Get "internal/defaults.yaml" | fromYaml)) }} +{{ $_ = set $rox "_defaults" $defaultsCfg }} +{{ $_ = include "srox.mergeInto" (list $rox $defaultsCfg.defaults) }} + + +{{/* Expand applicable config values */}} +{{ $expandables := $.Files.Get "internal/expandables.yaml" | fromYaml }} +{{ include "srox.expandAll" (list $ $rox $expandables) }} + +{{/* Initial image pull secret setup. + + Always assume that there are `stackrox` and `stackrox-scanner` image pull secrets, + even if they weren't specified. + This is required for updates anyway, so referencing it on first install will minimize a later + diff. */}} +{{ include "srox.configureImagePullSecrets" (list $ "imagePullSecrets" $._rox.imagePullSecrets "stackrox" (list "stackrox" "stackrox-scanner") $.Release.Namespace) }} + +{{/* Global CA setup */}} +{{ $caCertSpec := dict "CN" "StackRox Certificate Authority" "ca" true }} +{{ include "srox.configureCrypto" (list $ "ca" $caCertSpec) }} + +{{/* Additional CAs. */}} +{{ $additionalCAList := list }} +{{ if kindIs "string" $._rox.additionalCAs }} + {{ if trim $._rox.additionalCAs }} + {{ $additionalCAList = append $additionalCAList (dict "name" "ca.crt" "contents" $._rox.additionalCAs) }} + {{ end }} +{{ else if kindIs "slice" $._rox.additionalCAs }} + {{ range $contents := $._rox.additionalCAs }} + {{ $additionalCAList = append $additionalCAList (dict "name" "ca.crt" "contents" $contents) }} + {{ end }} +{{ else if kindIs "map" $._rox.additionalCAs }} + {{ range $name := keys $._rox.additionalCAs | sortAlpha }} + {{ $additionalCAList = append $additionalCAList (dict "name" $name "contents" (get $._rox.additionalCAs $name)) }} + {{ end }} +{{ else if not (kindIs "invalid" $._rox.additionalCAs) }} + {{ include "srox.fail" (printf "Invalid kind %s for additionalCAs" (kindOf $._rox.additionalCAs)) }} +{{ end }} +{{ range $path, $contents := .Files.Glob "secrets/additional-cas/**" }} + {{ $name := trimPrefix "secrets/additional-cas/" $path }} + {{ $additionalCAList = append $additionalCAList (dict "name" $name "contents" (toString $contents)) }} +{{ end }} +{{ $additionalCAs := dict }} +{{ range $idx, $elem := $additionalCAList }} + {{ if not (kindIs "string" $elem.contents) }} + {{ include "srox.fail" (printf "Invalid non-string contents kind %s at index %d (%q) of additionalCAs" (kindOf $elem.contents) $idx $elem.name) }} + {{ end }} + {{/* In a k8s secret, no characters other than alphanumeric, '.', '_' and '-' are allowed. Also, for the + update-ca-certificates script to work, the file names must end in '.crt'. */}} + + {{ $normalizedName := printf "%02d-%s.crt" $idx (regexReplaceAll "[^[:alnum:]._-]" $elem.name "-" | trimSuffix ".crt") }} + {{ $_ := set $additionalCAs $normalizedName $elem.contents }} +{{ end }} +{{ $_ = set $._rox "_additionalCAs" $additionalCAs }} + +{{/* Proxy configuration. + Note: The reason this is different is that unlike the endpoints config, the proxy configuration + might contain sensitive data and thus might _not_ be stored in the always available canonical + values file. However, this is probably rare. Therefore, for this particular instance we do decide + to rely on lookup magic for initially populating the secret with a default proxy config. + However, we won't take any chances, and therefore only create that secret if we can be reasonably + confident that lookup actually works, by trying to lookup the default service account. + */}} +{{ $proxyCfg := $env._proxyConfig }} +{{ $fileOut := dict }} +{{ include "srox.loadFile" (list $ $fileOut "config/proxy-config.yaml") }} +{{ if $fileOut.found }} + {{ if not (kindIs "invalid" $proxyCfg) }} + {{ include "srox.fail" "Both env.proxyConfig was specified, and a config/proxy-config.yaml was found. Please remove/rename the config file, or comment out the env.proxyConfig stanza." }} + {{ end }} + {{ $proxyCfg = $fileOut.contents }} +{{ end }} + +{{/* On first install, create a default proxy config, but only if we can be sure none exists. */}} +{{ if kindIs "invalid" $proxyCfg }} + {{ if $.Release.IsInstall }} + {{ $lookupOut := dict }} + {{ include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "proxy-config") }} + {{ if and $lookupOut.reliable (not $lookupOut.result) }} + {{ $fileOut := dict }} + {{ include "srox.loadFile" (list $ $fileOut "config/proxy-config.yaml.default") }} + {{ $proxyCfg = $fileOut.contents }} + {{ end }} + {{ end }} +{{ end }} +{{ $_ = set $env "_proxyConfig" $proxyCfg }} +{{ $_ = set $._rox "_renderMode" "renderAll" }} + +{{/* + Central setup. + */}} + + +{{ include "srox.centralSetup" $ }} + + +{{/* + Scanner setup. + */}} + +{{ $scannerCfg := $._rox.scanner }} + +{{ if and $scannerCfg.disable (or $.Release.IsInstall $.Release.IsUpgrade) }} + {{/* We generally don't recommend customers run without scanner, so show a warning to the user */}} + {{ $action := ternary "deploy StackRox Central Services without Scanner" "upgrade StackRox Central Services without Scanner (possibly removing an existing Scanner deployment)" $.Release.IsInstall }} + {{ include "srox.warn" (list $ (printf "You have chosen to %s. Certain features dependent on image scanning might not work." $action)) }} +{{ else if not $scannerCfg.disable }} + {{ if and (ne $scannerCfg.mode "full") (ne $scannerCfg.mode "") }} + {{ include "srox.fail" (print "Only scanner full mode is allowed in Central. To solve this, set to full mode: scanner.mode=full.") }} + {{ end }} + {{ include "srox.scannerInit" (list $ $scannerCfg) }} +{{ end }} + + +{{/* + Post-processing steps. + */}} + + +{{/* Compact the post-processing config to prevent it from appearing non-empty if it doesn't + contain any concrete (leaf) values. */}} +{{ include "srox.compactDict" (list $._rox._state.generated -1) }} + +{{/* Setup Image Pull Secrets for Docker Registry. + Note: This must happen afterwards, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} +{{ include "srox.configureImagePullSecretsForDockerRegistry" (list $ ._rox.imagePullSecrets) }} + +{{/* Final warnings based on state. */}} +{{ if $._rox._state.customCertGen }} + {{ include "srox.warn" (list $ "At least one certificate was generated by Helm. Helm limits the generation of custom certificates to RSA private keys, which have poorer computational performance. Consider using roxctl for certificate generation of certificates with ECDSA private keys for improved performance. (THIS IS NOT A SECURITY ISSUE)") }} +{{ end }} + +{{ end }} + +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_injected-ca-bundle.tpl b/rhacs/4.3.8/central-services/templates/_injected-ca-bundle.tpl new file mode 100644 index 0000000..f831139 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_injected-ca-bundle.tpl @@ -0,0 +1,29 @@ +{{/* + srox.injectedCABundleVolume + + Configures ConfigMap volume to use in a deployment. + */}} +{{- define "srox.injectedCABundleVolume" -}} +{{- if eq ._rox.env.openshift 4 }} +- name: trusted-ca-volume + configMap: + name: injected-cabundle-{{ .Release.Name }} + items: + - key: ca-bundle.crt + path: tls-ca-bundle.pem + optional: true +{{ end }} +{{ end }} + +{{/* + srox.injectedCABundleVolumeMount + + Mounts the srox.injectedCABundle volume to a container. + */}} +{{- define "srox.injectedCABundleVolumeMount" -}} +{{- if eq ._rox.env.openshift 4 }} +- name: trusted-ca-volume + mountPath: /etc/pki/injected-ca-trust/ + readOnly: true +{{ end }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_labels.tpl b/rhacs/4.3.8/central-services/templates/_labels.tpl new file mode 100644 index 0000000..b98b06c --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_labels.tpl @@ -0,0 +1,31 @@ +{{/* + srox._labels $labels $ $objType $objName $forPod + + Writes all applicable [pod] labels (including default labels) for $objType/$objName + into $labels. Pod labels are written iff $forPod is true. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.labels". + */}} +{{ define "srox._labels" }} +{{ $labels := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $forPod := index . 4 }} +{{ $_ := set $labels "app.kubernetes.io/name" "stackrox" }} +{{ $_ = set $labels "app.kubernetes.io/managed-by" $.Release.Service }} +{{ $_ = set $labels "helm.sh/chart" (printf "%s-%s" $.Chart.Name ($.Chart.Version | replace "+" "_")) }} +{{ $_ = set $labels "app.kubernetes.io/instance" $.Release.Name }} +{{ $_ = set $labels "app.kubernetes.io/version" $.Chart.AppVersion }} +{{ $_ = set $labels "app.kubernetes.io/part-of" "stackrox-central-services" }} +{{ $component := regexReplaceAll "^.*/\\d{2}-([a-z]+)-\\d{2}-[^/]+\\.yaml" $.Template.Name "${1}" }} +{{ if not (contains "/" $component) }} + {{ $_ = set $labels "app.kubernetes.io/component" $component }} +{{ end }} +{{ $metadataNames := list "labels" }} +{{ if $forPod }} + {{ $metadataNames = append $metadataNames "podLabels" }} +{{ end }} +{{ include "srox._customizeMetadata" (list $ $labels $objType $objName $metadataNames) }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_lookup.tpl b/rhacs/4.3.8/central-services/templates/_lookup.tpl new file mode 100644 index 0000000..2dc0aa9 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_lookup.tpl @@ -0,0 +1,40 @@ +{{/* + srox.safeLookup $ $out $apiVersion $kind $ns $name + + This function does nothing if $.meta.useLookup is false; otherwise, it will + perform a `lookup $apiVersion $kind $ns $name` operation and store the result in + $out.result. + + Additionally, if a lookup was attempted, $out.reliable will contain a bool indicating + whether the result of lookup can be relied upon. This is determined to be the case if + the default service account in the release namespace can be found. + */}} +{{ define "srox.safeLookup" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ if $._rox.meta.useLookup }} + {{ if kindIs "invalid" $._rox._state.lookupWorks }} + {{ $testOut := dict }} + {{ include "srox._doLookup" (list $ $testOut "v1" "ServiceAccount" $.Release.Namespace "default") }} + {{ $_ := set $._rox._state "lookupWorks" ($testOut.result | not | not) }} + {{ end }} + {{ include "srox._doLookup" . }} + {{ $_ := set $out "reliable" $._rox._state.lookupWorks }} +{{ end }} +{{ end }} + + +{{/* + srox._doLookup $ $out $apiVersion $kind $ns $name + + Calls "lookup" with arguments $apiVersion $kind $ns $name, and stores the result + in $out.result. + + This function exists to prevent a parse error if the lookup function isn't defined. It does + so by deferring the execution of lookup to a template string instantiated via `tpl`. + */}} +{{ define "srox._doLookup" }} +{{ $ := index . 0 }} +{{ $tplArgs := dict "Template" $.Template "out" (index . 1) "apiVersion" (index . 2) "kind" (index . 3) "ns" (index . 4) "name" (index . 5) }} +{{ $_ := tpl "{{ $_ := set .out \"result\" (lookup .apiVersion .kind .ns .name) }}" $tplArgs }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_metadata.tpl b/rhacs/4.3.8/central-services/templates/_metadata.tpl new file mode 100644 index 0000000..3ed131f --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_metadata.tpl @@ -0,0 +1,194 @@ +{{/* + srox.labels $ $objType $objName + + Format labels for $objType/$objName as YAML. + */}} +{{- define "srox.labels" -}} +{{- $labels := dict -}} +{{- $_ := include "srox._labels" (append (prepend . $labels) false) -}} +{{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.podLabels $ $objType $objName + + Format pod labels for $objType/$objName as YAML. + */}} +{{- define "srox.podLabels" -}} +{{- $labels := dict -}} +{{- $_ := include "srox._labels" (append (prepend . $labels) true) -}} +{{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.annotations $ $objType $objName + + Format annotations for $objType/$objName as YAML. + */}} +{{- define "srox.annotations" -}} +{{- $annotations := dict -}} +{{- $_ := include "srox._annotations" (append (prepend . $annotations) false) -}} +{{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.podAnnotations $ $objType $objName + + Format pod annotations for $objType/$objName as YAML. + */}} +{{- define "srox.podAnnotations" -}} +{{- $annotations := dict -}} +{{- $_ := include "srox._annotations" (append (prepend . $annotations) true) -}} +{{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.envVars $ $objType $objName $containerName + + Format environment variables for container $containerName in + $objType/$objName as YAML. + */}} +{{- define "srox.envVars" -}} +{{- $envVars := dict -}} +{{- $_ := include "srox._envVars" (prepend . $envVars) -}} +{{- range $k := keys $envVars | sortAlpha -}} +{{- $v := index $envVars $k }} +- name: {{ quote $k }} +{{- if kindIs "map" $v }} + {{- toYaml $v | nindent 2 }} +{{- else }} + value: {{ quote $v }} +{{- end }} +{{ end -}} +{{- end -}} + +{{/* + srox._annotations $annotations $ $objType $objName $forPod + + Writes all applicable [pod] annotations (including default annotations) for + $objType/$objName into $annotations. Pod labels are written iff $forPod is true. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.annotations". + */}} +{{ define "srox._annotations" }} +{{ $annotations := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $forPod := index . 4 }} +{{ $_ := set $annotations "meta.helm.sh/release-namespace" $.Release.Namespace }} +{{ $_ = set $annotations "meta.helm.sh/release-name" $.Release.Name }} +{{ $_ = set $annotations "owner" "stackrox" }} +{{ $_ = set $annotations "email" "support@stackrox.com" }} +{{ $metadataNames := list "annotations" }} +{{ if $forPod }} + {{ $metadataNames = append $metadataNames "podAnnotations" }} +{{ end }} +{{ include "srox._customizeMetadata" (list $ $annotations $objType $objName $metadataNames) }} +{{ end }} + +{{/* + srox._envVars $envVars $ $objType $objName $containerName + + Writes all applicable environment variables for $objType/$objName + into $envVars. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.envVars". + */}} +{{ define "srox._envVars" }} +{{ $envVars := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $containerName := index . 4 }} +{{ $metadataNames := list "envVars" }} +{{ include "srox._customizeMetadata" (list $ $envVars $objType $objName $metadataNames) }} +{{ if $containerName }} + {{ $containerKey := printf "/%s" $containerName }} + {{ $envVarsForContainer := index $envVars $containerKey }} + {{ if $envVarsForContainer }} + {{ include "srox.destructiveMergeOverwrite" (list $envVars $envVarsForContainer) }} + {{ end }} +{{ end }} + +{{/* Remove all entries starting with / */}} +{{ range $key, $_ := $envVars }} + {{ if hasPrefix "/" $key }} + {{ $_ := unset $envVars $key }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox._customizeMetadata $ $metadata $objType $objName $metadataNames + + Writes custom key/value metadata to $metadata by consulting all sub-dicts with names in + $metadataNames under the applicable custom metadata locations (._rox.customize, + ._rox.customize.other.$objType/*, ._rox.customize.other.$objType/$objName, and + ._rox.customizer.$objName [workloads only]). Dictionaries are consulted in this order, with + values from dictionaries consulted later overwriting values from dictionaries consulted + earlier. + */}} +{{ define "srox._customizeMetadata" }} +{{ $ := index . 0 }} +{{ $metadata := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $metadataNames := index . 4 }} + +{{ $overrideDictPaths := list "" (printf "other.%s/*" $objType) (printf "other.%s/%s" $objType $objName) }} +{{ if has $objType (list "deployment" "daemonset") }} + {{ $overrideDictPaths = append $overrideDictPaths $objName }} +{{ end }} + +{{ range $dictPath := $overrideDictPaths }} + {{ $customizeDict := $._rox.customize }} + {{ if $dictPath }} + {{ $resolvedOut := dict }} + {{ include "srox.safeDictLookup" (list $._rox.customize $resolvedOut $dictPath) }} + {{ $customizeDict = $resolvedOut.result }} + {{ end }} + {{ if $customizeDict }} + {{ range $metadataName := $metadataNames }} + {{ $customMetadata := index $customizeDict $metadataName }} + {{ include "srox.destructiveMergeOverwrite" (list $metadata $customMetadata) }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{/* Add namespace specific prefixes for global resources to avoid resource name clashes for multi-namespace deployments. */}} +{{- define "srox.globalResourceName" -}} +{{- $ := index . 0 -}} +{{- $name := index . 1 -}} + +{{- if eq $.Release.Namespace "stackrox" -}} + {{- /* Standard namespace, use resource name as is. */ -}} + {{- $name -}} +{{- else -}} + {{- /* Add global prefix to resource name. */ -}} + {{- printf "%s-%s" $._rox.globalPrefix (trimPrefix "stackrox-" $name) -}} +{{- end -}} +{{- end -}} + +{{/* + srox.initGlobalPrefix $ + + Initializes prefix for global resources. + */}} +{{- define "srox.initGlobalPrefix" -}} +{{- $ := index . 0 -}} +{{ if kindIs "invalid" $._rox.globalPrefix }} + {{ if eq $.Release.Namespace "stackrox" }} + {{ $_ := set $._rox "globalPrefix" "stackrox" }} + {{ else }} + {{ $_ := set $._rox "globalPrefix" (printf "stackrox-%s" (trimPrefix "stackrox-" $.Release.Namespace)) }} + {{ end }} +{{ end }} + +{{ if ne $._rox.globalPrefix "stackrox" }} + {{ include "srox.note" (list $ (printf "Global Kubernetes resources are prefixed with '%s'." $._rox.globalPrefix)) }} +{{- end -}} +{{- end -}} diff --git a/rhacs/4.3.8/central-services/templates/_openshift.tpl b/rhacs/4.3.8/central-services/templates/_openshift.tpl new file mode 100644 index 0000000..85201cb --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_openshift.tpl @@ -0,0 +1,47 @@ +{{/* + srox.autoSenseOpenshiftVersion $ + + This function detects the OpenShift version automatically based on the cluster the Helm chart is installed onto. + It writes the result to ._rox.env.openshift as an integer. + Possible results are: + - 3 (OpenShift 3) + - 4 (OpenShift 4) + - 0 (Non-Openshift cluster) + + If "true" is passed for $._rox.env.openshift the OpenShift version is detected based on the Kubernetes cluster version. + If the Kubernetes version is not available (i.e. when using Helm template) auto-sensing falls back on OpenShift 3 to be + backward compatible. + */}} + +{{ define "srox.autoSenseOpenshiftVersion" }} + +{{ $ := index . 0 }} +{{ $env := $._rox.env }} + +{{/* Infer OpenShift, if needed */}} +{{ if kindIs "invalid" $env.openshift }} + {{ $_ := set $env "openshift" (has "apps.openshift.io/v1" $._rox._apiServer.apiResources) }} +{{ end }} + +{{/* Infer openshift version */}} +{{ if and $env.openshift (kindIs "bool" $env.openshift) }} + {{/* Parse and add KubeVersion as semver from built-in resources. This is necessary to compare valid integer numbers. */}} + {{ $kubeVersion := semver $.Capabilities.KubeVersion.Version }} + + {{/* Default to OpenShift 3 if no openshift resources are available, i.e. in helm template commands */}} + {{ if not (has "apps.openshift.io/v1" $._rox._apiServer.apiResources) }} + {{ $_ := set $._rox.env "openshift" 3 }} + {{ else if gt $kubeVersion.Minor 11 }} + {{ $_ := set $env "openshift" 4 }} + {{ else }} + {{ $_ := set $env "openshift" 3 }} + {{ end }} + {{ include "srox.note" (list $ (printf "Based on API server properties, we have inferred that you are deploying into an OpenShift %d.x cluster. Set the `env.openshift` property explicitly to 3 or 4 to override the auto-sensed value." $env.openshift)) }} +{{ end }} +{{ if not (kindIs "bool" $env.openshift) }} + {{ $_ := set $env "openshift" (int $env.openshift) }} +{{ else if not $env.openshift }} + {{ $_ := set $env "openshift" 0 }} +{{ end }} + +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_psp.tpl b/rhacs/4.3.8/central-services/templates/_psp.tpl new file mode 100644 index 0000000..bffb2a0 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_psp.tpl @@ -0,0 +1,19 @@ +{{/* + srox.autoSensePodSecurityPolicies $ + */}} + +{{ define "srox.autoSensePodSecurityPolicies" }} + +{{ $ := index . 0 }} +{{ $system := $._rox.system }} + +{{ if kindIs "invalid" $system.enablePodSecurityPolicies }} + {{ $_ := set $system "enablePodSecurityPolicies" (has "policy/v1beta1" $._rox._apiServer.apiResources) }} + {{ if $system.enablePodSecurityPolicies }} + {{ include "srox.note" (list $ (printf "PodSecurityPolicies are enabled, since your environment supports them according to API server properties.")) }} + {{ else }} + {{ include "srox.note" (list $ (printf "PodSecurityPolicies are disabled, since your environment does not support them according to API server properties.")) }} + {{ end }} +{{ end }} + +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_reporting.tpl b/rhacs/4.3.8/central-services/templates/_reporting.tpl new file mode 100644 index 0000000..621e284 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_reporting.tpl @@ -0,0 +1,34 @@ +{{/* + srox.fail $message + + Print a nicely-formatted fatal error message and exit. + */}} +{{ define "srox.fail" }} +{{ printf "\n\nFATAL ERROR:\n%s" . | wrap 100 | fail }} +{{ end }} + +{{/* + srox.warn $ $message + + Add $message to the list of encountered warnings. + */}} +{{ define "srox.warn" }} +{{ $ := index . 0 }} +{{ $msg := index . 1 }} +{{ $warnings := $._rox._state.warnings }} +{{ $warnings = append $warnings $msg }} +{{ $_ := set $._rox._state "warnings" $warnings }} +{{ end }} + +{{/* + srox.note $ $message + + Add $message to the list notes that will be shown to the user after installation/upgrade. + */}} +{{ define "srox.note" }} +{{ $ := index . 0 }} +{{ $msg := index . 1 }} +{{ $notes := $._rox._state.notes }} +{{ $notes = append $notes $msg }} +{{ $_ := set $._rox._state "notes" $notes }} +{{ end }} diff --git a/rhacs/4.3.8/central-services/templates/_scanner_init.tpl b/rhacs/4.3.8/central-services/templates/_scanner_init.tpl new file mode 100644 index 0000000..75fbe95 --- /dev/null +++ b/rhacs/4.3.8/central-services/templates/_scanner_init.tpl @@ -0,0 +1,40 @@ +{{/* + srox.scannerInit . $scannerConfig + + Initializes the scanner configuration. The scanner chart has two modes "full" and + "slim". + The "full" mode is used for stand-alone deployments, mostly along with StackRox's Central service. In this + mode, the image contains vulnerability data and the Helm chart can create its own certificates. + + The "slim" mode is used to deploy Scanner with a smaller image and does not generate TLS certificates, + typically deployed within a Secured Cluster to scan images stored in a registry only accessible to the current cluster. + The scanner chart defaults to "full" mode if no mode was provided. + + $scannerConfig contains all values which are configured by the user. The structure can be viewed in the according + config-shape. See internal/scanner-config-shape.yaml. + */}} + +{{ define "srox.scannerInit" }} + +{{ $ := index . 0 }} +{{ $scannerCfg := index . 1 }} + +{{ if or (eq $scannerCfg.mode "") (eq $scannerCfg.mode "full") }} + {{ include "srox.configureImage" (list $ $scannerCfg.image) }} + {{ include "srox.configureImage" (list $ $scannerCfg.dbImage) }} + + {{ $scannerCertSpec := dict "CN" "SCANNER_SERVICE: Scanner" "dnsBase" "scanner" }} + {{ include "srox.configureCrypto" (list $ "scanner.serviceTLS" $scannerCertSpec) }} + + {{ $scannerDBCertSpec := dict "CN" "SCANNER_DB_SERVICE: Scanner DB" "dnsBase" "scanner-db" }} + {{ include "srox.configureCrypto" (list $ "scanner.dbServiceTLS" $scannerDBCertSpec) }} +{{ else if eq $scannerCfg.mode "slim" }} + {{ include "srox.configureImage" (list $ $scannerCfg.slimImage) }} + {{ include "srox.configureImage" (list $ $scannerCfg.slimDBImage) }} +{{ else }} + {{ include "srox.fail" (printf "Unknown scanner mode %s" $scannerCfg.mode) }} +{{ end }} + +{{ include "srox.configurePassword" (list $ "scanner.dbPassword") }} + +{{ end }} diff --git a/rhacs/4.3.8/central-services/values-private.yaml.example b/rhacs/4.3.8/central-services/values-private.yaml.example new file mode 100644 index 0000000..41254aa --- /dev/null +++ b/rhacs/4.3.8/central-services/values-private.yaml.example @@ -0,0 +1,178 @@ +# StackRox Kubernetes Security Platform - Central Services Chart +# PRIVATE configuration file. +# +# This file contains sensitive values relevant for the deployment of the +# StackRox Kubernetes Platform Central Services components. +# +# Apart from image pull secrets (see below), all the values in this file are +# optional or can be automatically generated at deployment time. +# Moreover, this file does not need to be provided (e.g., via `-f`) to a `helm upgrade` +# command, even if custom values are used - the previously set values +# will simply be preserved. +# +# The following values typically require user input, as they cannot be automatically generated +# (though each of them can be omitted): +# - `imagePullSecrets.username` and `imagePullSecrets.password` +# - `env.proxyConfig` +# - `central.defaultTLS` +# +# If you do choose to use this file (either by manually filling in values, or by +# generating it via the `roxctl central generate` command family), you must store +# it in a safe and secure place, such as a secrets management system. +# + +# # BEGIN CONFIGURATION VALUES SECTION + +# # Image pull credentials. If you do not specify these, you need to specify one of +# # the following: +# # - `imagePullSecrets.allowNone=true`: in case your registry allows pulling images without +# # credentials. +# # - `imagePullSecrets.useExisting="secret1;secret2;..."`: in case you have pre-existing image +# # pull secrets with the given name already created in the target namespace. +# # - `imagePullSecrets.useFromDefaultServiceAccount=true`: in case the default service account +# # in the target namespace is configured with sufficiently scoped image pull secrets. +# # If you do not know if any of the above applies to your situation, your best course of +# # action is probably to enter your image pull credentials here. +# imagePullSecrets: +# username: +# password: +# +# # Proxy configuration. This will only be required if you are running in an environment +# # where internet access is not possible by default. +# # Since this configuration may contain a proxy password, it is treated as a sensitive +# # piece of configuration. +# # The following example is a stripped-down one. For a full documentation, see the file +# # `config/proxy-config.yaml.default` that is shipped with this chart. +# env: +# proxyConfig: | +# url: http://proxy.name:port +# username: username +# password: password +# excludes: +# - some.domain +# +# +# # TLS Certificate Configuration. +# # Most of the following values are not typically required to be populated manually. You can +# # either omit them, in which case they will be auto-generated upon initial installation, +# # or they are populated when you invoke `roxctl central generate` to generate deployment +# # files. +# +# # Certificate Authority (CA) certificate for TLS certificates used internally +# # by StackRox services. +# ca: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Secret configuration options for the StackRox Central deployment. +# central: +# # Private key to use for signing JSON web tokens (JWTs), which are used +# # for authentication. Omit to auto-generate (initial deployment) or use existing +# # (upgrade). +# jwtSigner: +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# # Internal "central.stackrox" service TLS certificate for the Central deployment. +# # Omit to auto-generate (initial deployment) or use existing (upgrade). +# serviceTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Default (user-facing) TLS certificate. +# # NOTE: In contrast to almost all other configuration options, this IS expected +# # to be manually populated. While any existing default TLS certificate secret +# # will be re-used on upgrade if this is omitted, nothing will be created on +# # initial deployment if this is not populated. +# defaultTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Administrator password for logging in to the StackRox portal. +# # You can either specify a plaintext password here, or an htpasswd file with a +# # bcrypt-encrypted password. +# # If you omit this setting, a password will be automatically generated upon initial +# # installation, and the existing administrator password secret will be re-used upon +# # upgrades. +# adminPassword: +# # The plaintext value of the administrator password. If you specify a password here, +# # you must omit the `htpasswd` setting. +# value: +# # The htpasswd contents of the administrator login credentials. If you specify a +# # value here, you must omit the `value` setting. +# # The password hash MUST be bcrypt. +# htpasswd: | +# admin: +# +# # Secret configuration options for the StackRox Central DB deployment. +# db: +# # The password to be used for authenticating central database access IF USING POSTGRES. +# # This is not user-relevant and only serves to properly secure the database with a +# # pre-shared secret. If this setting is omitted, a password will be automatically generated +# # upon initial deployment, and the existing password will be used upon upgrades. +# password: +# # The plaintext value of the administrator password. +# value: +# # Internal "central-db.stackrox.svc" service TLS certificate for the Central DB deployment. +# # Omit to auto-generate (initial deployment) or use existing (upgrade). +# serviceTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Secret configuration options for the StackRox Central deployment. +# scanner: +# # The password to be used for authenticating database access. This is not user-relevant +# # and only serves to properly secure the database with a pre-shared secret. If this +# # setting is omitted, a password will be automatically generated upon initial deployment, +# # and the existing password will be used upon upgrades. +# dbPassword: +# value: +# +# # Internal "scanner.stackrox.svc" service TLS certificate for the Scanner deployment. +# # Omit to auto-generate (initial deployment) or use existing (upgrade). +# serviceTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- +# +# # Internal "scanner-db.stackrox" service TLS certificate for the Scanner DB deployment. +# # Omit to auto-generate (initial deployment) or use existing (upgrade). +# dbServiceTLS: +# cert: | +# -----BEGIN CERTIFICATE----- +# +# -----END CERTIFICATE----- +# key: | +# -----BEGIN RSA PRIVATE KEY----- +# +# -----END RSA PRIVATE KEY----- diff --git a/rhacs/4.3.8/central-services/values-public.yaml.example b/rhacs/4.3.8/central-services/values-public.yaml.example new file mode 100644 index 0000000..4458bdd --- /dev/null +++ b/rhacs/4.3.8/central-services/values-public.yaml.example @@ -0,0 +1,538 @@ +# StackRox Kubernetes Security Platform - Central Services Chart +# PUBLIC configuration file. +# +# This file contains general configuration values relevant for the deployment of the +# StackRox Kubernetes Platform Central Services components, which do not contain or reference +# sensitive data. This file can and should be stored in a source code management system +# and should be referenced on each `helm upgrade`. +# +# Most of the values in this file are optional, and you only should need to make modifications +# if the default deployment configuration is not sufficient for you for whatever reason. +# The most notable exception is the `imagePullSecrets` section, which needs to be configured +# according to the registry access in your environment. +# +# Other than that, the following are sections most likely require custom configuration: +# - `image.registry`: if you are pulling images from a registry other than `registry.redhat.io/advanced-cluster-security`. +# - `env.offlineMode`: if you want to run StackRox in offline mode. +# - `central.endpointsConfig`: if you want to expose additional endpoints (such as endpoints +# without TLS) in Central. +# - `central.resources`: if the default resource configuration for Central is not adequate +# for your environment. +# - `db.persistence`: for configuring where Central DB stores its postgres database volume. + +# # BEGIN CONFIGURATION VALUES SECTION + +# imagePullSecrets: +# # allowNone=true indicates that no image pull secrets are required to be configured +# # upon initial deployment. Use this setting if you are using a cluster-private registry +# # that does not require authentication. +# allowNone: false +# +# # useExisting specifies a list of existing Kubernetes image pull secrets in the target +# # namespace that should be used for trying to pull StackRox images. Use this if you have +# # your custom way of injecting image pull secrets. +# useExisting: +# - secret1 +# - secret2 +# +# # useFromDefaultServiceAccount=true will instruct the deployment logic to use any +# # image pull secrets referenced by the default service account in the target namespace. +# # This is a common way to grant namespace-wide access to a Docker image registry. +# # This behavior is the default, set the value to `false` if you do not want this. +# useFromDefaultServiceAccount: true +# +# image: +# # The registry relative to which all image references are resolved, unless +# # a specific registry is provided for particular workloads which takes precedence +# # (see `central.image`, `db.image`, `scanner.image`, and `scanner.dbImage` below). +# # This can be just a registry hostname such as `stackrox.io`, or a registry hostname with +# # a "remote" component such as `us.gcr.io/my-stackrox-mirror`. +# registry: us.gcr.io/my-stackrox-mirror +# +# env: +# # Treat the environment as an OpenShift cluster. Leave this unset to use auto-detection +# # based on available API resources on the server. +# # Set it to true to auto-detect the OpenShift version, otherwise set it explicitly. +# # Possible values: null, false, true, 3, 4 +# openshift: false +# +# # Whether the target cluster is an Istio-enabled cluster. If you deploy via `helm install`, +# # this can typically be determined automatically, so we recommend to not set a value here. +# # Set to true or false explicitly to override the auto-sensing logic only. +# istio: false +# +# # The "platform" of the target cluster into which StackRox is being deployed. This can +# # be the name of an infrastructure provider or product, and will tailor the StackRox +# # deployment to the respective target environment. Currently, the only supported platforms +# # are "default" and "gke". +# # If you deploy via `helm install`, the environment can typically be determined automatically, +# # choose a fixed value here only if you want to override the auto-sensing logic. +# platform: default +# +# # offlineMode=true instructs StackRox to not attempt any outgoing connections to the +# # internet. Use this in air-gapped environments, where it's important that workloads do +# # not even try to make outbound connections. Defaults to `false` when omitted. +# offlineMode: false +# +# # Additional certificate authorities (CAs) to trust, besides system roots. +# # Use this setting if Central or Scanner need to reach out to services that use certificates +# # issued by an authority in your organization, but are NOT globally trusted. In these cases, +# # specify the root CA certificate of your organization. +# additionalCAs: +# acme-labs-ca.crt: | +# -----BEGIN CERTIFICATE----- +# [... base64 (PEM) encoded certificate data ...] +# -----END CERTIFICATE----- +# +# # Public configuration options for the StackRox Central deployment. +# central: +# # General configuration options for the Central deployment. +# # See the `config/central/config.yaml.default` file that is shipped with this chart +# # for a fully documented version. +# config: | +# maintenance: +# safeMode: false +# compaction: +# enabled: true +# bucketFillFraction: .5 +# freeFractionThreshold: 0.75 +# # Configuration option for rolling back to a previous version after an upgrade has been completed. +# # Default to none. +# # By default, the user may initiate a rollback if upgrade fails before Central has started. +# # Users may rollback to their previous version once Central has started, but this may result in data loss, +# # so users must explicitly specify the version they are rolling back to in order to acknowledge the effects. +# forceRollbackVersion: 3.0.58.0 +# +# # Additional endpoints configuration for the Central deployment. +# # See the `config/central/endpoints.yaml.default` file that is shipped with this chart +# # for a fully documented version. +# endpointsConfig: | +# endpoints: +# - listen: ":8080" +# protocols: +# - http +# tls: +# disable: true +# +# # If you want to use a monitoring solution such as Prometheus, set the following value to +# # "true" to make a /metrics endpoint for Central available on port 9090. +# exposeMonitoring: true +# +# # If you want to enforce StackRox Central to only run on certain nodes, you can specify +# # a node selector here to make sure Central can only be scheduled on Nodes with the +# # given label. This is particular relevant for the "hostPath" persistence type. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-central +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # Central is single-homed, so avoid preemptible nodes. +# - weight: 100 +# preference: +# matchExpressions: +# - key: cloud.google.com/gke-preemptible +# operator: NotIn +# values: +# - "true" +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/infra +# operator: Exists +# - weight: 25 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/compute +# operator: Exists +# # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in +# # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/master +# operator: DoesNotExist +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/control-plane +# operator: DoesNotExist +# +# # Configures the Central image to be used. Most users will only need to configure a +# # custom registry (if any) at the global scope, and do not require any settings here. +# image: +# # A custom registry that will override the global `image.registry` setting for the +# # Central image. +# registry: us.gcr.io/stackrox-central-repo +# +# # A custom image name that will override the default `main`. +# name: custom-main +# +# # A custom image tag that will override the default tag based on the current +# # StackRox version. +# # IMPORTANT: If you set a value here, you will lose the ability to simply upgrade +# # by running `helm upgrade` against a more recent chart version. You MUST increment +# # the version referenced in this tag for every upgrade. It is therefore strongly +# # recommended that if you choose to mirror StackRox images in your own registry, +# # you preserve all image tags as-is. +# tag: custom-version +# +# # A full image name override that will be used as-is for the StackRox Central image. +# # This is only required in very rare circumstances, and its use is strongly discouraged. +# # If set, all other image-related values will be ignored for the StackRox Central image. +# # The following example value lists the full image ref that would be constructed from +# # the above components. +# fullRef: "us.gcr.io/stackrox-central-repo/custom-main:custom-version" +# +# # Custom resource overrides for the Central deployment. Use this if your environment is +# # very large or very small, and the default resource configuration does not provide +# # satisfactory performance. +# resources: +# requests: +# memory: "4Gi" +# cpu: "1500m" +# limits: +# memory: "8Gi" +# cpu: "4000m" +# +# # Configuration for exposing the StackRox Central deployment for external access. +# # Generally, only ONE of the nested values should be specified. If none is specified, +# # the Central deployment will not be exposed, and you must either manually expose it, +# # or access it via port-forwarding. +# exposure: +# # Exposure via a Kubernetes LoadBalancer service. +# loadBalancer: +# enabled: true +# # The port on which to expose StackRox Central. Defaults to 443. +# port: 443 +# # The static IP to assign to the load balancer. Defaults to dynamic. +# ip: 10.0.0.0 +# +# # Exposure via a Kubernetes NodePort service. +# nodePort: +# enabled: true +# # The port on the node under which to expose the service. Omit this for +# # letting Kubernetes automatically select a node port (recommended). +# port: 32000 +# +# # Exposure via an OpenShift route. Only available for OpenShift clusters +# route: +# enabled: true +# +# # Additional volume mounts for the Central container. Only few people will require this. +# extraMounts: +# - name: my-configmap # the name of the volume +# # The source of the volume. This will be embedded as-is in the `volume:` section of the +# # pod spec. +# source: +# configMap: +# name: my-configmap +# # The mount point of the volume. This will be embedded as-is in the `volumeMounts:` section +# # of the pod spec. +# mount: +# mountPath: /etc/my-config-data +# +# # Public configuration options for the StackRox Central DB: +# db: +# # If you want to enforce StackRox Central DB to only run on certain nodes, you can specify +# # a node selector here to make sure Central can only be scheduled on Nodes with the +# # given label. This is particular relevant for the "hostPath" persistence type. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-central-db +# +# # If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# # External signifies that a Postgres wire-compatible database has already been deployed and a Central DB pod +# # does not need to be deployed +# external: false +# +# # Customized Central DB source configurations to connect to Postgres database. +# # Default configurations are applied if the configurations are omitted. +# source: +# # ConnectionString should not be specified if the Central DB deployment is being managed by the helm chart +# # The connection string must be in the format described here https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING +# # The only connection string format supported is as specified in "34.1.1.1. Keyword/Value Connection Strings" +# # client_encoding=UTF8 is required in any connection string and the only supported encoding +# # statementTimeoutMs is ignored for external database connections +# # If using a connection that supports "statement_timeout" it is recommended to include "statement_timeout=1200000" +# # Do NOT use a connection string with a password field. Instead specify the value below in the password section in values-private.yaml. +# connectionString: "host=central-db.stackrox port=5432 user=postgres sslmode=verify-full" +# minConns: 10 +# maxConns: 90 +# statementTimeoutMs: 1200000 +# +# # Configures the Central DB image to be used. Most users will only need to configure a +# # custom registry (if any) at the global scope, and do not require any settings here. +# image: +# # A custom registry that will override the global `image.registry` setting for the +# # Central DB image. +# registry: us.gcr.io/central-db +# # A custom image name that will override the default `main`. +# name: custom-central-db +# # A custom image tag that will override the default tag based on the current +# # StackRox version. +# tag: custom-version +# +# # Custom resource overrides for the Central DB deployment. +# resources: +# requests: +# memory: "8Gi" +# cpu: "4" +# limits: +# memory: "16Gi" +# cpu: "8" +# +# # Persistence configuration for the StackRox Central DB. +# # Exactly ONE of the nested values should be specified. If none is specified, +# # the StackRox Central DB will be configured with the default PVC-based persistence. +# persistence: +# # The path on the node where to store the StackRox Central DB volume +# # when using host path persistence. +# hostPath: /var/lib/central-db +# # The persistent volume claim details when storing the StackRox database +# # on a persistent volume managed by a Kubernetes persistent volume claim (PVC). +# persistentVolumeClaim: +# # The name of the claim. This defaults to central-db if not set. +# claimName: central-db +# # Whether to create the claim upon deployment. The default is true; set this to false +# # if you have a pre-existing persistent volume claim that you want to use. +# createClaim: true +# # The storage class of the persistent volume. +# storageClass: stackrox-gke-ssd +# # The size of the persistent volume managed by the claim, in Gigabytes (or with an +# # explicit unit, such as "1Ti"). Defaults to 100Gi. +# size: 100 +# # If you want to bind a preexisting persistent volume, you can specify it here. +# volume: +# volumeSpec: +# # The section includes volume type specific config, the volume type can be: +# # gcePersistentDisk, hostpath, filestore(nfs) etc. +# gcePersistentDisk: +# # Type specific parameters. The specified persistent volume should have +# # been created. +# pdName: gke-pv +# +# # Public configuration options for the StackRox Scanner. +# scanner: +# # disable=true will cause the StackRox Kubernetes Security Platform to be +# # deployed without the StackRox Scanner, meaning that certain functionalities +# # may not be available. If this setting is changed prior to a `helm upgrade` +# # invocation, the existing StackRox scanner deployment will be removed. +# disable: false +# +# # The number of replicas for the Scanner deployment. If autoscaling is enabled (see below), +# # this determines the initial number of replicas. +# replicas: 3 +# +# # The log level for the scanner deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce StackRox Scanner to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-scanner +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# podAntiAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 100 +# podAffinityTerm: +# labelSelector: +# matchLabels: +# app: scanner +# topologyKey: kubernetes.io/hostname +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/infra +# operator: Exists +# - weight: 25 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/compute +# operator: Exists +# # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in +# # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/master +# operator: DoesNotExist +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/control-plane +# operator: DoesNotExist +# +# # If you want to enforce StackRox Scanner DB to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner DB can only be scheduled on Nodes with the +# # given label. +# dbNodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-scanner-db +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# dbTolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# # Configuration for autoscaling the Scanner deployment. +# autoscaling: +# # disable=true causes autoscaling to be disabled. All other settings in this section +# # will have no effect. +# disable: false +# # The minimum number of replicas for autoscaling. The following value is the default. +# minReplicas: 2 +# # The maximum number of replicas for autoscaling. The following value is the default. +# maxReplicas: 5 +# +# # Custom resource overrides for the Scanner deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "4Gi" +# cpu: "2000m" +# +# # Custom resource overrides for the Scanner DB deployment. +# dbResources: +# limits: +# cpu: "2000m" +# memory: "4Gi" +# requests: +# cpu: "200m" +# memory: "200Mi" +# +# # Custom configuration of the image to be used for the Scanner deployment. +# # See `central.image` for a full example. +# image: +# registry: us.gcr.io/stackrox-scanner-repo +# name: scanner # "scanner" is the default +# +# dbImage: +# registry: us.gcr.io/stackrox-scanner-db-repo +# name: scanner-db # "scanner-db" is the default +# +# +# # Customization Settings. +# # The following allows specifying custom Kubernetes metadata (labels and annotations) +# # for all objects instantiated by this Helm chart, as well as additional pod labels, +# # pod annotations, and container environment variables for workloads. +# # The configuration is hierarchical, in the sense that metadata that is defined at a more +# # generic scope (e.g., for all objects) can be overridden by metadata defined at a narrower +# # scope (e.g., only for the central deployment). +# customize: +# # Extra metadata for all objects. +# labels: +# my-label-key: my-label-value +# annotations: +# my-annotation-key: my-annotation-value +# +# # Extra pod metadata for all objects (only has an effect for workloads, i.e., deployments). +# podLabels: +# my-pod-label-key: my-pod-label-value +# podAnnotations: +# my-pod-annotation-key: my-pod-annotation-value +# +# # Extra environment variables for all containers in all objects. +# envVars: +# MY_ENV_VAR_NAME: MY_ENV_VAR_VALUE +# +# # Extra metadata for the central deployment only. +# central: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the central db deployment only. +# db: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the scanner deployment only. +# scanner: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the scanner-db deployment only. +# scanner-db: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for all other objects. The keys in the following map can be +# # an object name of the form "service/central-loadbalancer", or a reference to all +# # objects of a given type in the form "service/*". The values under each key +# # are the five metadata overrides (labels, annotations, podLabels, podAnnotations, envVars) +# # as specified above, though only the first two will be relevant for non-workload +# # object types. +# other: +# "service/*": +# labels: {} +# annotations: {} +# +# # EXPERT SETTINGS +# # The following settings should only be changed if you know very well what you are doing. +# # The scenarios in which these are required are generally not supported. +# +# # Set allowNonstandardNamespace=true if you are deploying into a namespace other than +# # "stackrox". This has been observed to work in some case, but is not generally supported. +# allowNonstandardNamespace: false +# +# # Set allowNonstandardReleaseName=true if you are deploying with a release name other than +# # the default "stackrox-central-services". This has been observed to work in some cases, +# # but is not generally supported. +# allowNonstandardReleaseName: false + +# monitoring: +# # Enables integration with OpenShift platform monitoring. +# openshift: +# enabled: true diff --git a/rhacs/4.3.8/central-services/values.yaml b/rhacs/4.3.8/central-services/values.yaml new file mode 100644 index 0000000..b8a6a4d --- /dev/null +++ b/rhacs/4.3.8/central-services/values.yaml @@ -0,0 +1,364 @@ +## StackRox Central chart default settings file. +## +## This file includes the default settings for the StackRox Central chart. +## It serves as a form of documentation for all the possible settings that a +## user can override are. HOWEVER, if you want to override some settings, DO NOT +## create a copy of this file to be used as a baseline, or modify it in place. +## Instead, create a file that contains only those settings you want to override, +## and pass it to helm or roxctl via the `-f` parameter. +## +## For example, if you want to disable the deployment of scanner, create a file +## `values-override.yaml` (or any name you choose) with the following contents: +## +## scanner: +## disable: true +## +## and then invoke helm by passing `-f values-override.yaml` to +## `helm install`/`helm upgrade`. +## +## Alternatively, if you want to override just a few values, you can set them directly +## via the `--set` command, e.g., +## $ helm install --set scanner.disable=true ... +## +## Note that an arbitrary number of `-f` and `--set` parameters can be combined. It is +## generally a good practice to store secret data such as the admin password separate from +## non-sensitive configuration data. +## +# +## Configuration for image pull secrets. +## These should usually be set via the command line when running `helm install`, e.g., +## helm install --set imagePullSecrets.username=myuser --set imagePullSecrets.password=mypass, +## or be stored in a separate YAML-encoded secrets file. +#imagePullSecrets: +# # Username and password to be used for pulling images. +# # These should usually be set via the command line when running `helm install`, e.g., +# # helm install --set imagePullSecrets.username=myuser --set imagePullSecrets.password=mypass, +# # or be stored in a separate YAML-encoded secrets file. +# username: null +# password: null +# +# # If no image pull secrets are provided, an installation would usually fail. In order to +# # prevent it from failing, this option must explicitly be set to true. +# allowNone: false +# +# # If there exist available image pull secrets in the cluster that are managed separately, +# # set this value to the list of the respective secret names. While it is recommended to +# # record the secret names in a persisted YAML file, providing a single string containing +# # a comma-delimited list of secret names is also supported, for easier interaction with +# # --set. +# useExisting: [] +# +# # Whether to import any secrets from the default service account existing in the StackRox +# # namespace. The default service account often contains "standard" image pull secrets that +# # should be used by default for image pulls, hence this defaults to true. Only has an effect +# # if server-side lookups are enabled. +# useFromDefaultServiceAccount: true +# +## Common settings for all image properties +#image: +# # The image registry to use. Unless overridden in the more specific configs, this +# # determines the base registry for each image referenced in this config file. +# registry: registry.redhat.io/advanced-cluster-security +# +## Settings regarding the installation environment +#env: +# # Treat the environment as an OpenShift cluster. Leave this unset to use auto-detection +# # based on available API resources on the server. +# # Possible values: null, false, true, 3, 4 +# openshift: null +# +# # Treat the environment as Istio-enabled. Leave this unset to use auto-detection based on +# # available API resources on the server. +# # Possible values: null, false, true +# istio: null +# +# # The cloud provider platform where the target Kubernetes cluster is running. Leave this +# # unset to use auto-detection based on the Kubernetes version. +# # Possible values: null, "default", "gke" +# platform: null +# +# # Whether to run StackRox in offline mode. When run in offline mode, no connections to external +# # endpoints will be made. +# offlineMode: false +# +# # The proxy configuration for Central and Scanner, specified either as an embedded YAML +# # directionary, or as an (expandable) string. +# proxyConfig: null +# +# +## Settings for the StackRox Service CA certificates. +## If `cert` and `key` are both set (it is an error to set only one of the two), the corresponding +## values are used as the PEM-encoded certificate and private key for the internal Service CA. +## If they are left unspecified, they are generated under the following conditions: +## - `generate` is explicitly set to true, or +## - `generate` is unset (null), and the Helm chart is being freshly installed (as opposed to being +## upgraded). +#ca: +# cert: null +# key: null +# generate: null +# + +## Additional CA certificates to trust, besides system roots +## If specified, this should be a map mapping file names to PEM-encoded contents. +#additionalCAs: null +# +central: +# # Settings for telemetry data collection. + telemetry: + enabled: false + storage: + endpoint: "" + key: "" +# +# +# config: "@config/central/config.yaml|config/central/config.yaml.default" +# +# endpointsConfig: "@config/central/endpoints.yaml|config/central/endpoints.yaml.default" +# +# +# nodeSelector: null +# +# jwtSigner: +# key: null +# generate: null +# +# # Settings for the internal service-to-service TLS certificate used by central. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# defaultTLS: +# cert: null +# key: null +# +# image: +# registry: null +# name: main +# tag: 4.0.0 +# fullRef: null +# +# adminPassword: +# value: null +# generate: null +# htpasswd: null +# +# resources: +# requests: +# memory: "4Gi" +# cpu: "1500m" +# limits: +# memory: "8Gi" +# cpu: "4000m" +# +# persistence: +# hostPath: null +# persistentVolumeClaim: +# claimName: null +# createClaim: null +# storageClass: null +# size: null +# none: null +# +# exposure: +# +# # LoadBalancer configuration. +# # Disabled by default. +# # Default port is 443. +# loadBalancer: +# enabled: null +# port: null +# ip: null +# +# # NodePort configuration. +# # Disabled by default. +# nodePort: +# enabled: null +# port: null +# +# # Route configuration. +# # Disabled by default. +# route: +# enabled: null +# # Specify a custom hostname if desired, otherwise accept the default from OpenShift. +# host: null +# +# db: +# # External signifies that a Postgres wire-compatible database has already been deployed and a Central DB pod +# # does not need to be deployed +# external: false +# +# source: +# # ConnectionString should not be specified if the Central DB deployment is being managed by the helm chart +# # The connection string must be in the format described here https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING +# # client_encoding=UTF8 is required in any connection string and the only supported encoding +# # statementTimeoutMs is ignored for external database connections +# # If using a connection that supports "statement_timeout" it is recommended to include "statement_timeout=1200000" +# # Do NOT use a connection string with a password field. Instead specify the value below in the password section/ +# connectionString: null +# minConns: 10 +# maxConns: 90 +# statementTimeoutMs: 1200000 +# +# # The admin password setting for communication with Central's DB. +# # When a value is set explicitly, this is always used, even on upgrade. +# # Otherwise, a password will be automatically generated if `generate` is set to true, +# # or left unset (null) and the Helm chart is being installed (as opposed to upgraded). +# # Should only be used when utilizing Postgres as central's DB +# password: +# value: null +# generate: null +# +# postgresConfig: "@config/centraldb/postgresql.conf|config/centraldb/postgresql.conf.default" +# hbaConfig: "@config/centraldb/pg_hba.conf|config/centraldb/pg_hba.conf.default" +# +# # Specifying configOverride mounts the specified config map in the same namespace which must contain +# # both pg_hba.conf and postgresql.conf. This should only be used when the default settings are not +# # sufficient and manual override is required. +# configOverride: null +# +# nodeSelector: null +# +# # Settings for the internal service-to-service TLS certificate used by central. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# image: +# registry: null +# name: central-db +# tag: 4.0.0 +# fullRef: null +# +# resources: +# requests: +# memory: "8Gi" +# cpu: "4" +# limits: +# memory: "16Gi" +# cpu: "8" +# +# persistence: +# hostPath: null +# persistentVolumeClaim: +# claimName: null +# createClaim: null +# storageClass: null +# size: null +# none: null +# +## Configuration options relating to StackRox Scanner. +#scanner: +# # If this is set to true, StackRox will be deployed without scanner. No other setting in this +# # section will have any effect. +# disable: false +# +# # Default number of scanner replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 3 +# +# logLevel: INFO +# +# # Settings related to autoscaling the scanner deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any effect. +# disable: false +# minReplicas: 1 +# maxReplicas: 5 +# +# # Resource settings for the scanner deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "4Gi" +# cpu: "2000m" +# +# image: +# registry: null +# name: scanner +# tag: 2.3.2 +# fullRef: null +# +# dbImage: +# registry: null +# name: scanner-db +# tag: 2.3.2 +# fullRef: null +# +# # Resource settings for the scanner-db deployment. +# dbResources: +# limits: +# cpu: 2 +# memory: 4Gi +# requests: +# cpu: 200m +# memory: 200Mi +# +# # The admin password setting for communication with scanner's DB. +# # When a value is set explicitly, this is always used, even on upgrade. +# # Otherwise, a password will be automatically generated if `generate` is set to true, +# # or left unset (null) and the Helm chart is being installed (as opposed to upgraded). +# dbPassword: +# value: null +# generate: null +# +# # Settings for the internal service-to-service TLS certificate used by scanner. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# # Settings for the internal service-to-service TLS certificate used by scanner-db. +# # See the documentation for `ca` at the top level for an explanation. +# dbServiceTLS: +# cert: null +# key: null +# generate: null +# +## EXPERT SETTINGS. You usually do not need to touch those. +# +## If set to true, allow deploying in a namespace other than "stackrox". This is unsupported, so +## use at your own risk. +#allowNonstandardNamespace: false +# +## If set to true, allow a release name other than "stackrox-central-services". There are no issues +## with that, but for streamlining purposes, we want to encourage all users to stick with the +## default name, and make it a little harder to deviate from that. +#allowNonstandardReleaseName: false +# +#meta: +# # This controls whether the built-in `lookup` function will be used. If you see an error +# # about there being no function `lookup`, set this to `false` (might be required on Helm +# # versions before 3.1). +# useLookup: true +# +# # This is a dictionary from file names to contents that can be used to inject files that +# # would usually be included via .Files.Get into the chart rendering. +# fileOverrides: {} +# +# # This configuration section allows overriding settings that would be inferred from the +# # running API server. +# apiServer: +# # The Kubernetes version running on the API server. This is used for auto-detection +# # of the platform. +# version: null +# # The list of available API resources on the server, in the form of "apps/v1" or +# # "apps/v1/Deployment". This is used to detect environment capabilities. +# overrideAPIResources: null +# # A list of extra API resources that should be assumed to exist on the API server. This +# # can be used in conjunction with both data obtained from the API server, or data set +# # via `overrideAPIResources`. +# extraAPIResources: [] +# +#monitoring: +# # Enables integration with OpenShift platform monitoring. +# openshift: +# enabled: true diff --git a/rhacs/4.3.8/secured-cluster-services/.helmignore b/rhacs/4.3.8/secured-cluster-services/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/rhacs/4.3.8/secured-cluster-services/Chart.yaml b/rhacs/4.3.8/secured-cluster-services/Chart.yaml new file mode 100644 index 0000000..bd8aec9 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: stackrox-secured-cluster-services +icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/Red_Hat-Hat_icon.png +description: Helm Chart for StackRox Secured Clusters +type: application +version: 400.3.8 +appVersion: 4.3.8 diff --git a/rhacs/4.3.8/secured-cluster-services/README.md b/rhacs/4.3.8/secured-cluster-services/README.md new file mode 100644 index 0000000..d77e5ef --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/README.md @@ -0,0 +1,468 @@ +# StackRox Kubernetes Security Platform - Secured Cluster Services Helm Chart + +This Helm chart allows you to deploy the necessary services on a StackRox +secured cluster: StackRox Sensor, StackRox Collector, and StackRox Admission +Control. +If you want to install Secured Cluster Services for Red Hat Advanced Cluster Security, +refer to [Installing the secured-cluster-services Helm chart](https://docs.openshift.com/acs/installing/installing_helm/install-helm-quick.html#installing-secured-cluster-services-quickly_acs-install-helm-quick). + +## Prerequisites + +To deploy the secured cluster services for the StackRox Kubernetes Security Platform, you must: +- Have at least version 3.1 of the Helm tool installed on your machine + +> **IMPORTANT** +> +> We publish new Helm charts with every new release of the StackRox Kubernetes +> Security Platform. Make sure to use a version of this chart that matches the +> StackRox Kubernetes Security Platform version you have installed. + +## Add the canonical chart location as a Helm repository + +The canonical repository for StackRox Helm charts is https://mirror.openshift.com/pub/rhacs/charts. +To use StackRox Helm charts, run the following command: +```sh +helm repo add stackrox https://mirror.openshift.com/pub/rhacs/charts +``` +Only run this command once per machine on which you want to use StackRox Helm +charts. + +Before you deploy or upgrade a chart from a remote repository, you must +run the following command: +```sh +helm repo update +``` + +## Install Secured Cluster Services + +Installing a new StackRox secured cluster requires a *cluster init bundle*. You +can generate a **cluster init bundle** by using the `roxctl` CLI or the StackRox +portal. You can use the same bundle to set up multiple StackRox secured +clusters by providing it as an input to the `helm install` command. + +> **NOTE**: +> +> - The following sections assume that you have a safe way to pass secrets to +> the helm command. +> - If not, you can decouple secret creation from installing or upgrading the +> Helm chart, see [Deployment with pre-created secrets](#deployment-with-pre-created-secrets) for more information. + +### Generate cluster init bundle + +Run the following command to generate a **cluster init bundle**: +```sh +roxctl central init-bundles generate --output cluster-init-bundle.yaml +``` + +- This command creates a **cluster init bundle** called + `cluster-init-bundle.yaml`. +- Make sure that you store this bundle securely as it contains secrets. You can + use the same bundle to set up multiple StackRox secured clusters. + +### Deploy Secured Cluster Services + +You can use the following command to deploy secured cluster services by using +this Helm chart: +```sh +helm install -n stackrox --create-namespace \ + stackrox-secured-cluster-services stackrox/stackrox-secured-cluster-services \ + -f \ + --set clusterName= \ + --set centralEndpoint= +``` +- In this command, you can replace the chart name + `stackrox/stackrox-secured-cluster-services` with the chart's file path if you have it + locally. +- The provided cluster name can either denote the intended name for a new secured cluster + or the name of an existing cluster, in which case the name will be reused and associated + with the Kubernetes cluster on which the chart is installed. + +After you deploy the StackRox Kubernetes Security Platform Secured Cluster +Services using the `helm install` command, you will see informative notes and +warnings related to the installation. The new cluster automatically registers +itself to StackRox Central, and it is visible in the StackRox portal as a +Helm-managed cluster. If the provided cluster name is already associated with +an existing secured cluster, the name will be reused and associated with the +cluster on which the chart is installed. + +In case you use image mirroring or otherwise access StackRox container images from non-standard location, +you may also need to provide image pull credentials. +There are several ways to inject the required credentials (if any) into the installation process: + +- **Explicitly specify username and password:** Use this if you are using a registry that supports username/password + authentication. Pass the following arguments to the `helm install` command: + ```sh + --set imagePullSecrets.username= --set imagePullSecrets.password= + ``` +- **Use pre-existing image pull secrets:** If you already have one or several image pull secrets + created in the namespace to which you are deploying, you can reference these in the following + way (we assume that your secrets are called `pull-secret-1` and `pull-secret-2`): + ```sh + --set imagePullSecrets.useExisting="pull-secret-1;pull-secret-2" + ``` +- **Do not use image pull secrets:** If you are pulling your images from quay.io/stackrox-io or a registry in a private + network that does not require authentication, or if the default service account in the namespace + to which you are deploying is already configured with appropriate image pull secrets, you do + not need to specify any additional image pull secrets. + +### Applying custom configuration options + +The secured cluster services Helm chart has many different configuration +options. You can directly specify these options when you run the `helm install` +command for simple use cases. + +However, we recommend storing your configuration in a file and using that file +for future upgrades or reconfiguration using the `helm upgrade` command. + +#### Specifying options with `--set` parameter + +You can use the `--set` and `--set-file` parameter with the `helm install` +command to specify various options to customize deployments quickly. However, +don't use them for specifying complex configurations. + +For example, +- **Configure cluster environment**: + ```sh + --set env.openshift=true + ``` +- **Configure collection method**: + ```sh + --set collector.collectionMethod=EBPF + ``` + +#### Using configuration YAML files and the `-f` command-line option + +We recommended that you store all custom configuration options in persisted files. + +The Secured Cluster Services Helm chart contains example configuration files +(called `values-public.yaml.example` and `values-private.yaml.example`), that list +all the available configuration options, along with documentation. + +The following sample configuration file (`secured-cluster.yaml`) uses a few of +the options which you can configure: +- **`values-public.yaml`:** + ```yaml + clusterName: "acme-cluster-01" + centralEndpoint: "central.acme-labs.internal" + + env: + istio: true # enable istio support + + sensor: + # Use custom resource overrides for sensor + resources: + requests: + cpu: "2" + memory: "4Gi" + limits: + cpu: "4" + memory: "8Gi" + + admissionControl: + dynamic: + disableBypass: true # Disable bypassing of Admission Controller + + customize: + # Apply the important-service=true label for all objects managed by this chart. + labels: + important-service: true + # Set the CLUSTER=important-cluster environment variable for all containers in the + # collector deployment: + collector: + envVars: + CLUSTER: important-cluster + ``` +- **`values-private.yaml`**: + ```yaml + imagePullSecrets: + username: + password: + ``` + +After you have created these YAML files, you can inject the configuration options into the +installation process via the `-f` flag, i.e., by appending the following options to the +`helm install` invocation: +```sh +helm install ... -f values-public.yaml -f values-private.yaml +``` + +#### Changing configuration options after deployment + +To make changes to the configuration of an existing deployment of the StackRox +Secured Cluster Services: +1. Change the configuration options in your YAML configuration file(s). +1. Use the `-f` option and specify the configuration file's path when you + run the `helm upgrade` command. + +For example, to apply configuration changes for the secured cluster, use the following command: +```sh +helm upgrade -n stackrox \ + stackrox-secured-cluster-services stackrox/stackrox-secured-cluster-services \ + --reuse-values \ + -f values-public.yaml \ + -f values-private.yaml +``` + +You can also specify configuration values using the `--set` or `--set-file` +parameters. However, these options aren't saved, and you'll have to specify all +the options again manually. + +#### Changing cluster name after deployment + +To change the name of the cluster shown in the StackRox portal, you must specify +values for both the `--clusterName` and the `--confirmNewClusterName` options: + +```sh +helm upgrade -n stackrox stackrox-secured-cluster-services --clusterName= --confirmNewClusterName= +``` + +> **NOTE:** +> +> When you change the cluster name: +> - The StackRox Kubernetes Security Platform either creates a new cluster or +> reuses an existing cluster if a cluster with the same name already exists. +> - The StackRox Kubernetes Security Platform doesn't rename the old cluster. +> The old cluster still shows up in the StackRox portal, but it doesn't +> receive any data. You must remove the old cluster if you don't want to see +> it in the StackRox portal. + +### Configuration + +The following table lists some common configuration parameters of this Helm +chart and their default values: + +|Parameter |Description | Default value | +|:---------|:-----------|:--------------| +|`clusterName`| Name of your cluster. | | +|`confirmNewClusterName`| You don't need to change this unless you upgrade and change the value for `clusterName`. In this case, set it to the new value of `clusterName`. This option exists to prevent you from [accidentally creating a new cluster with a different name](#changing-cluster-after-deployment). | `null` | +|`centralEndpoint`| Address of the Central endpoint, including the port number (without a trailing slash). If you are using a non-gRPC capable LoadBalancer, use the WebSocket protocol by prefixing the endpoint address with `wss://`. |`central.stackrox.svc:443` | +|`clusterLabels`| Custom labels associated with a secured cluster | `{}` | +|`additionalCAs`| Use it to add (named) PEM-encoded CA certificates for Sensor. | `{}` | +|`imagePullSecrets.username`| Specify username for accessing image registry. |`null`| +|`imagePullSecrets.password`| Specify password for accessing image registry. |`null`| +|`imagePullSecrets.useExisting`| Specify existing Kubernetes image pull secrets that should be used for trying to pull StackRox images. |`[]`| +|`imagePullSecrets.useFromDefaultServiceAccount`| This setting controls whether image pull secrets from a default service account in the target namespace should be used for image pulls. |`true`| +|`imagePullSecrets.useExisting`| Specify existing Kubernetes image pull secrets that should be used for trying to pull StackRox images. |`[]`| +|`imagePullSecrets.allowNone`| Enabling this setting indicates that no image pull secrets are required to be configured upon initial deployment. Use this setting if you are using a cluster-private registry that does not require authentication. |`false`| +|`image.main.name`|Repository from which to download the main image. |`main` | +|`image.collector.name`|Repository from which to download the collector image. |`collector` | +|`image.main.registry`| Address of the registry you are using for main image.|`registry.redhat.io/advanced-cluster-security` | +|`image.collector.registry`| Address of the registry you are using for collector image.|`registry.redhat.io/advanced-cluster-security` | +|`sensor.endpoint`| Address of the Sensor endpoint including port number. No trailing slash.|`sensor.stackrox.svc:443` | +|`collector.collectionMethod`|Either `EBPF`, `CORE_BPF`, or `NO_COLLECTION`. |`EBPF` | +|`collector.disableTaintTolerations`|If you specify `false`, tolerations are applied to collector, and the collector pods can schedule onto all nodes with taints. If you specify it as `true`, no tolerations are applied, and the collector pods won't scheduled onto nodes with taints. |`false` | +|`collector.slimMode`| Specify `true` if you want to use a slim Collector image for deploying Collector. Using slim Collector images requires Central to provide the matching kernel module or eBPF probe. If you are running the StackRox Kubernetes Security Platform in offline mode, you must download a kernel support package from [stackrox.io](https://install.stackrox.io/collector/support-packages/index.html) and upload it to Central for slim Collectors to function. Otherwise, you must ensure that Central can access the online probe repository hosted at https://collector-modules.stackrox.io/.|`false` | +|`admissionControl.listenOnCreates`| This setting controls whether the cluster is configured to contact the StackRox Kubernetes Security Platform with `AdmissionReview` requests for `create` events on Kubernetes objects. |`false` | +|`admissionControl.listenOnUpdates`|This setting controls whether the cluster is configured to contact the StackRox Kubernetes Security Platform with `AdmissionReview` requests for `update` events on Kubernetes objects.|`false` | +|`admissionControl.listenOnEvents`|This setting controls whether the cluster is configured to contact the StackRox Kubernetes Security Platform with `AdmissionReview` requests for `update` Kubernetes events like `exec` and `portforward`.|`false` on OpenShift, `true` otherwise.| +|`admissionControl.dynamic.enforceOnCreates`| It controls whether the StackRox Kubernetes Security Platform evaluates policies; if it’s disabled, all `AdmissionReview` requests are automatically accepted. You must specify `listenOnCreates` as `true` for this to work. |`false` | +|`admissionControl.dynamic.enforceOnUpdates`| It controls whether the StackRox Kubernetes Security Platform evaluates policies for object updates; if it’s disabled, all `AdmissionReview` requests are automatically accepted. You must specify `listenOnUpdates` as `true` for this to work. |`false`| +|`admissionControl.dynamic.scanInline`| |`false` | +|`admissionControl.dynamic.disableBypass`|Set it to `true` to disable [bypassing the admission controller](https://help.stackrox.com/docs/manage-security-policies/use-admission-controller-enforcement/). |`false` | +|`admissionControl.dynamic.timeout`|The maximum time in seconds, the StackRox Kubernetes Security Platform should wait while evaluating admission review requests. Use it to set request timeouts when you enable image scanning. If the image scan runs longer than the specified time, the StackRox Kubernetes Security Platform accepts the request. Other enforcement options, such as scaling the deployment to zero replicas, are still applied later if the image violates applicable policies.|`3` | +|`registryOverride`|Use this parameter to override the default `docker.io` registry. Specify the name of your registry if you are using some other registry.| | +|`createUpgraderServiceAccount`| Specify `true` to create the `sensor-upgrader` account. By default, the StackRox Kubernetes Security Platform creates a service account called `sensor-upgrader` in each secured cluster. This account is highly privileged but is only used during upgrades. If you don’t create this account, you will have to complete future upgrades manually if the Sensor doesn’t have enough permissions. See [Enable automatic upgrades for secured clusters](https://help.stackrox.com/docs/configure-stackrox/enable-automatic-upgrades/) for more information.|`false` | +|`createSecrets`| Specify `false` to skip the orchestrator secret creation for the sensor, collector, and admission controller. | `true` | +|`customize`|Modern interface for specifying custom metadata for resources, including labels, annotations and environment variables. See below for more information.|`{}`| + + +The following table lists some advanced parameters, and you'll only need them in +non-standard environments: + +|Parameter |Description | Default value | +|:---------|:-----------|:--------------| +|`image.main.tag`| Tag of `main` image to use.|`null` | +|`image.collector.tag`| Tag of `collector` image to use.| `null` | +|`image.main.pullPolicy`| Image pull policy for `main` images.|`IfNotPresent`| +|`image.collector.pullPolicy`| Image pull policy for `collector` images.| `IfNotPresent` if `slimCollector` is enabled, `Always` otherwise.| +|`sensor.resources`|Resource specification for Sensor.|See below.| +|`collector.resources`|Resource specification for Collector.|See below.| +|`collector.complianceResources`|Resource specification for Collector's Compliance container.|See below.| +|`collector.nodeScanningResources`|Resource specification for Collector's Node Inventory container.|See below.| +|`collector.nodeSelector` | Node selector for Collector pods placement. | `null` (no placement constraints) | +|`admissionControl.resources`|Resource specification for Admission Control.|See below.| +|`sensor.imagePullPolicy`| Kubernetes image pull policy for Sensor. | `IfNotPresent` | +|`sensor.nodeSelector` | Node selector for Sensor pod placement. | `null` (no placement constraints) | +|`collector.imagePullPolicy`| Kubernetes image pull policy for Collector. | `Always` when deploying in slim mode, otherwise `IfNotPresent`. | +|`collector.complianceImagePullPolicy`| Kubernetes image pull policy for Collector. | `IfNotPresent` | +|`admissionControl.imagePullPolicy`| Kubernetes image pull policy for Admission Control. | `IfNotPresent` | +|`admissionControl.nodeSelector` | Node selector for Admission Control pods placement. | `null` (no placement constraints) | +|`exposeMonitoring`| This setting controls whether the monitoring port (TCP 9090) should be exposed on the services. | `false` | +|`env.openshift`| The StackRox Kubernetes Security Platform automatically detects the OpenShift version (`3.x` or `4.x`). Use this parameter to override the automatically detected version number, for example `4`. | `null` | +|`env.istio`| This setting can be used for overwriting the auto-sensing of Istio environments. If enabled, the cluster is set up for an Istio environment. | Auto-sensed, depends on environment. | +|`scanner.disable`| Scan images stored in the cluster's local registries. This variable is only available for the OpenShift Container Platform. | `true` | + +### Default resources + +Each container's default resource settings are defined in the +`internal/defaults.yaml` file in this chart. The following table lists the YAML +paths to the respective defaults for each container that this chart deploys: + +|Container |Path in `internal/defaults.yaml` | +|:----------------|:------------------------------------------| +|Sensor |`defaults.sensor.resources` | +|Collector |`defaults.collector.resources` | +|Compliance |`defaults.collector.complianceResources` | +|NodeInventory |`defaults.collector.nodeScanningResources`| +|Admission Control|`defaults.admissionControl.resources` | + +### Customization settings + +The `customize` setting allows specifying custom Kubernetes metadata (labels and +annotations) for all objects created by this Helm chart and additional pod +labels, pod annotations, and container environment variables for workloads. + +The configuration is hierarchical, in the sense that metadata defined at a more +generic scope (for example, for all objects) can be overridden by metadata +defined at a narrower scope (for example, only for the sensor deployment). + +For example: + +``` +customize: + # Extra metadata for all objects. + labels: + my-label-key: my-label-value + annotations: + my-annotation-key: my-annotation-value + # Extra pod metadata for all objects (only has an effect for workloads, i.e., deployments and daemonsets). + podLabels: + my-pod-label-key: my-pod-label-value + podAnnotations: + my-pod-annotation-key: my-pod-annotation-value + # Extra environment variables for all containers in all workloads. + envVars: + MY_ENV_VAR_NAME: MY_ENV_VAR_VALUE + # Extra metadata for the central deployment only. + sensor: + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + envVars: {} + # Extra metadata for the collector deployment only. + collector: + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + envVars: {} + # Extra metadata for the admission-control deployment only. + admission-control: + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + envVars: {} + # Extra metadata for all other objects. The keys in the following map can be + # an object name of the form "service/sensor", or a reference to all + # objects of a given type in the form "service/*". The values under each key + # are the five metadata overrides (labels, annotations, podLabels, podAnnotations, envVars) + # as specified above, though only the first two will be relevant for non-workload + # object types. + other: + "service/*": + labels: {} + annotations: {} +``` + +## Deployment with pre-created secrets + +The init bundle that you pass to the `helm` command using the `-f` flag creates +Kubernetes secrets for TLS certificates. If you don't want Helm to manage your +Kubernetes secrets, you can deploy the Secured Cluster Services chart without +creating secrets. However, it requires that you always specify the StackRox CA +certificate while installing or upgrading the Helm chart. This certificate +doesn't need to be kept secret. + +1. **Obtain the CA certificate configuration** either through the StackRox + portal or by using the `roxctl` CLI. + - **StackRox portal**: + 1. Navigate to **Platform Configuration** > **Integrations**. + 1. Under the **Authentication Tokens** section, select **Cluster Init Bundle**. + 1. Select **Get CA Config** on the top right to download the configuration + file called `ca-config.yaml`. + - **`roxctl CLI**: + 1. Run the following command: + ```sh + roxctl central init-bundles fetch-ca --output ca-config.yaml + ``` + This command writes the CA certificate configuration in a file called + `ca-config.yaml`. +1. **Use the CA certificate configuration in your Helm installation**. When you + run the `helm install` or the `helm upgrade` command, + pass the option `-f ca-config.yaml`: + ```sh + helm install -n stackrox stackrox-secured-cluster-services stackrox/stackrox-secured-cluster-services \ + -f ca-config.yaml \ + + ``` +1. **Disable TLS secret creation**. To prevent Helm from creating Kubernetes + secrets for the StackRox service certificates, set the `createSecrets` option + to `false`. You can either specify `createSecrets` option in a YAML + configuration file (such as `values-public.yaml`) or pass it to the `helm` + command by adding the `--set createSecrets=false` option. + +### Required Kubernetes secrets + +The following list contains the Kubernetes `Secret` objects that you need to +create in the `stackrox` namespace (or the custom namespace you are using) if +you configure the Helm chart to not create TLS certificate secrets. + +- `sensor-tls` with data: + - `ca.pem`: PEM-encoded StackRox CA certificate + - `sensor-cert.pem`: PEM-encoded StackRox Sensor certificate + - `sensor-key.pem`: PEM-encoded private key for the StackRox Sensor certificate +- `collector-tls` with data: + - `ca.pem`: PEM-encoded StackRox CA certificate + - `collector-cert.pem`: PEM-encoded StackRox Collector certificate + - `collector-key.pem`: PEM-encoded private key for the StackRox Collector certificate +- `admission-control-tls` with data: + - `ca.pem`: PEM-encoded StackRox CA certificate + - `admission-control-cert.pem`: PEM-encoded StackRox Admission Control certificate + - `admission-control-key.pem`: PEM-encoded private key for the StackRox Admision Control certificate + +#### Obtaining secrets for an existing cluster + +If you upgrade from a previous Helm chart, you can create certificates specific +to a particular cluster by using the following `roxctl` CLI command: + +```sh +export ROX_API_TOKEN= +roxctl -e sensor generate-certs +``` +Running this command create a file called `cluster--tls.yaml` in +the current directory. The file contains YAML manifests for the +[required Kubernetes secrets](#required-kubernetes-secrets). + +#### Obtaining secrets for an init bundle + +If you want to deploy multiple clusters using this Helm chart and want to create +certificates that can be used to register new clusters on-the-fly, you can +obtain the contents of an init bundle in the form of Kubernetes secrets. You can +use the StackRox portal or the `roxctl` CLI for this. + +- **Using the StackRox portal**: + 1. Navigate to **Platform Configuration** > **Integrations**. + 1. Under the **Authentication Tokens** section, select **Cluster Init Bundle**. + 1. Select the add **+** icon on the top left and enter a name for the new init + bundle. + 1. Select **Generate**. + 1. Select **Download Kubernetes Secrets File** at the bottom to save the + Kubernetes manifests to a file called + `-cluster-init-secrets.yaml`. +- **Using the `roxctl` CLI**: + 1. run the following command: + ```sh + roxctl central init-bundles generate --output-secrets cluster-init-secrets.yaml + ``` + This command stores the Kubernetes secret manifests for the cluster init + certificates in a file called `cluster-init-secrets.yaml`. + +You can then use the YAML file to generate secrets through any method that you like, for example, using Sealed Secrets. + +> **NOTE** +> +> Even when you use the certificates from an init bundle, you still need to +> specify the CA certificate configuration every time you install or upgrade the +> Helm chart. diff --git a/rhacs/4.3.8/secured-cluster-services/assets/Red_Hat-Hat_icon.png b/rhacs/4.3.8/secured-cluster-services/assets/Red_Hat-Hat_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fae985e3b0e5cfbcd1aa58e4a5b9d99f0274d937 GIT binary patch literal 7393 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 literal 0 HcmV?d00001 diff --git a/rhacs/4.3.8/secured-cluster-services/assets/StackRox_icon.png b/rhacs/4.3.8/secured-cluster-services/assets/StackRox_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3c136e3990a7382e8742c9079028abe00697c82c GIT binary patch literal 13406 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 literal 0 HcmV?d00001 diff --git a/rhacs/4.3.8/secured-cluster-services/config-templates/scanner/config.yaml.tpl b/rhacs/4.3.8/secured-cluster-services/config-templates/scanner/config.yaml.tpl new file mode 100644 index 0000000..5efc0b9 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/config-templates/scanner/config.yaml.tpl @@ -0,0 +1,48 @@ +{{- /* + This is the configuration file template for Scanner. + Except for in extremely rare circumstances, you DO NOT need to modify this file. + All config options that are possibly dynamic are templated out and can be modified + via `--set`/values-files specified via `-f`. + */ -}} + +# Configuration file for scanner. + +scanner: + centralEndpoint: https://central.{{ .Release.Namespace }}.svc + sensorEndpoint: https://sensor.{{ .Release.Namespace }}.svc + database: + # Database driver + type: pgsql + options: + # PostgreSQL Connection string + # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING + source: host=scanner-db.{{ .Release.Namespace }}.svc port=5432 user=postgres sslmode={{- if eq .Release.Namespace "stackrox" }}verify-full{{- else }}verify-ca{{- end }} statement_timeout=60000 + + # Number of elements kept in the cache + # Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database. + cachesize: 16384 + + api: + httpsPort: 8080 + grpcPort: 8443 + + updater: + # Frequency with which the scanner will poll for vulnerability updates. + interval: 5m + + logLevel: {{ ._rox.scanner.logLevel }} + + # The scanner intentionally avoids extracting or analyzing any files + # larger than the following default sizes to prevent DoS attacks. + # Leave these commented to use a reasonable default. + + # The max size of files in images that are extracted. + # Increasing this number increases memory pressure. + # maxExtractableFileSizeMB: 200 + # The max size of ELF executable files that are analyzed. + # Increasing this number may increase disk pressure. + # maxELFExecutableFileSizeMB: 800 + # The max size of image file reader buffer. Image file data beyond this limit are overflowed to temporary files on disk. + # maxImageFileReaderBufferSizeMB: 100 + + exposeMonitoring: false diff --git a/rhacs/4.3.8/secured-cluster-services/internal/cluster-config.yaml.tpl b/rhacs/4.3.8/secured-cluster-services/internal/cluster-config.yaml.tpl new file mode 100644 index 0000000..a85ddd7 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/cluster-config.yaml.tpl @@ -0,0 +1,33 @@ +{{- if ._rox.clusterName }} +clusterName: {{ ._rox.clusterName }} +{{- end }} +managedBy: {{ ._rox.managedBy }} +notHelmManaged: {{ eq ._rox.managedBy "MANAGER_TYPE_MANUAL" }} +clusterConfig: + staticConfig: + {{- if not ._rox.env.openshift }} + type: KUBERNETES_CLUSTER + {{- else }} + type: {{ if eq (int ._rox.env.openshift) 4 -}} OPENSHIFT4_CLUSTER {{- else -}} OPENSHIFT_CLUSTER {{ end }} + {{- end }} + mainImage: {{ coalesce ._rox.image.main._abbrevImageRef ._rox.image.main.fullRef }} + collectorImage: {{ coalesce ._rox.image.collector._abbrevImageRef ._rox.image.collector.fullRef }} + centralApiEndpoint: {{ ._rox.centralEndpoint }} + collectionMethod: {{ ._rox.collector.collectionMethod | upper | replace "-" "_" }} + admissionController: {{ ._rox.admissionControl.listenOnCreates }} + admissionControllerUpdates: {{ ._rox.admissionControl.listenOnUpdates }} + admissionControllerEvents: {{ ._rox.admissionControl.listenOnEvents }} + tolerationsConfig: + disabled: {{ ._rox.collector.disableTaintTolerations }} + slimCollector: {{ ._rox.collector.slimMode }} + dynamicConfig: + disableAuditLogs: {{ ._rox.auditLogs.disableCollection | not | not }} + admissionControllerConfig: + enabled: {{ ._rox.admissionControl.dynamic.enforceOnCreates }} + timeoutSeconds: {{ ._rox.admissionControl.dynamic.timeout }} + scanInline: {{ ._rox.admissionControl.dynamic.scanInline }} + disableBypass: {{ ._rox.admissionControl.dynamic.disableBypass }} + enforceOnUpdates: {{ ._rox.admissionControl.dynamic.enforceOnUpdates }} + registryOverride: {{ ._rox.registryOverride }} + configFingerprint: {{ ._rox._configFP }} + clusterLabels: {{- toYaml ._rox.clusterLabels | nindent 4 }} diff --git a/rhacs/4.3.8/secured-cluster-services/internal/compatibility-translation.yaml b/rhacs/4.3.8/secured-cluster-services/internal/compatibility-translation.yaml new file mode 100644 index 0000000..4e33afc --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/compatibility-translation.yaml @@ -0,0 +1,137 @@ +# Configuration compatibility layer translation rules. +# +# This file is a YAML file describing an object following the shape of the legacy Chart configuration. +# Each leaf object is a config fragment template, that will be merged into the user-specified config when specified +# by the user. +# +# The config fragment templates may reference the values ".value" and ".rawValue", the former containing the +# JSON-encoded value of the input field, the latter containing the value as a parsed object. + +cluster: + name: | + clusterName: {{ .value }} + type: | + env: + openshift: {{ if eq .rawValue "OPENSHIFT4_CLUSTER" }} 4 {{ else }} {{ eq .rawValue "OPENSHIFT_CLUSTER" }} {{ end }} + +endpoint: + central: | + centralEndpoint: {{ .value }} + advertised: | + sensor: + endpoint: {{ .value }} + +image: + repository: + main: | + image: + main: + name: {{ .value }} + collector: | + image: + collector: + name: {{ .value }} + registry: + main: | + image: + main: + registry: {{ .value }} + collector: | + image: + collector: + registry: {{ .value }} + pullPolicy: + main: | + image: + main: + pullPolicy: {{ .value }} + collector: | + image: + collector: + pullPolicy: {{ .value }} + tag: + main: | + image: + main: + tag: {{ .value}} + collector: | + image: + collector: + tag: {{ .value }} + +config: + collectionMethod: | + collector: + collectionMethod: {{ .value }} + + dynamic: + enforce: null # bool + scanInline: null # bool + disableBypass: null # bool + timeout: null # natural number + enforceOnUpdates: null # bool + + admissionControl: + createService: | + admissionControl: + listenOnCreates: {{ .value }} + listenOnUpdates: | + admissionControl: + listenOnUpdates: {{ .value }} + listenOnEvents: | + admissionControl: + listenOnEvents: {{ .value }} + enableService: | + admissionControl: + dynamic: + enforceOnCreates: {{ .value }} + enforceOnUpdates: | + admissionControl: + dynamic: + enforceOnUpdates: {{ .value }} + scanInline: | + admissionControl: + dynamic: + scanInline: {{ .value }} + disableBypass: | + admissionControl: + dynamic: + disableBypass: {{ .value }} + timeout: | + admissionControl: + dynamic: + timeout: {{ .value }} + registryOverride: | + registryOverride: {{ .value }} + disableTaintTolerations: | + collector: + disableTaintTolerations: {{ .value }} + createUpgraderServiceAccount: | + createUpgraderServiceAccount: {{ .value }} + createSecrets: | + createSecrets: {{ .value }} + offlineMode: null # not used + slimCollector: | + collector: + slimMode: {{ .value }} + sensorResources: | + sensor: + resources: {{ .value }} + admissionControlResources: | + admissionControl: + resources: {{ .value }} + collectorResources: | + collector: + resources: {{ .value }} + complianceResources: | + collector: + complianceResources: {{ .value }} + exposeMonitoring: | + exposeMonitoring: {{ .value }} + +envVars: | + customize: + envVars: + {{- range $_, $v := .rawValue }} + {{ quote $v.name }}: {{ quote $v.value }} + {{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/internal/config-shape.yaml b/rhacs/4.3.8/secured-cluster-services/internal/config-shape.yaml new file mode 100644 index 0000000..57450fa --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/config-shape.yaml @@ -0,0 +1,162 @@ +clusterName: null # string +clusterLabels: null # dict +confirmNewClusterName: null # string +centralEndpoint: null # string +registryOverride: null # string +exposeMonitoring: null # bool +createUpgraderServiceAccount: null # string +helmManaged: null +createSecrets: null +additionalCAs: null # [obj] +imagePullSecrets: + username: null # string + password: null # string + allowNone: null # bool + useExisting: null # string | [string] + useFromDefaultServiceAccount: null # bool +mainImagePullSecrets: + username: null # string + password: null # string + useExisting: null # string | [string] + useFromDefaultServiceAccount: null # bool + allowNone: null # bool +collectorImagePullSecrets: + username: null # string + password: null # string + useExisting: null # string | [string] + useFromDefaultServiceAccount: null # bool + allowNone: null # bool +image: + registry: null # string + main: + registry: null # string + name: null # string + repository: null # string + tag: null # string + fullRef: null # string + pullPolicy: null # string + collector: + slim: + fullRef: null # string + full: + fullRef: null # string + registry: null # string + name: null # string + repository: null # string + tag: null # string + fullRef: null # string + pullPolicy: null # string + scanner: + registry: null # string + name: null # string + repository: null # string + tag: null # string + fullRef: null # string + scannerDb: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string +env: + openshift: null # bool | int + istio: null # bool +ca: + cert: null # string +sensor: + imagePullPolicy: null # string + endpoint: null # string + affinity: null # dict + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + exposeMonitoring: null # bool + nodeSelector: null # string | dict + tolerations: null # [dict] + localImageScanning: + # Enables the local image scanning feature in Sensor. This disabled if local image scanning should not be used to prevent + # sensor reaching out to a scanner instance. + # This setting does not relate to the scanner deployment configuration which configures whether scanner should be deployed. + enabled: null # bool +admissionControl: + listenOnCreates: null # bool + listenOnUpdates: null # bool + listenOnEvents: null # bool + dynamic: + enforceOnCreates: null # bool + scanInline: null # bool + disableBypass: null # bool + timeout: null # natural number + enforceOnUpdates: null # bool + imagePullPolicy: null # string + replicas: null # int + affinity: null # dict + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + exposeMonitoring: null # bool + nodeSelector: null # string | dict + tolerations: null # [dict] +collector: + collectionMethod: null # string + disableTaintTolerations: null # bool + slimMode: null # bool + imagePullPolicy: null # string + tolerations: null # [dict] + resources: null # string | dict + complianceImagePullPolicy: null # string + complianceResources: null # string | dict + nodeScanningResources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + exposeMonitoring: null # bool + nodeSelector: null # string | dict + disableSELinuxOptions: null # bool + seLinuxOptionsType: null # string +auditLogs: + disableCollection: null # bool +customize: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + sensor: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + admission-control: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + collector: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + other: {} # dict +allowNonstandardNamespace: null # bool +allowNonstandardReleaseName: null # bool +enableOpenShiftMonitoring: null # bool +monitoring: + openshift: + enabled: null # bool +meta: + namespaceOverride: null # bool + useLookup: null # bool + fileOverrides: {} # dict + configFingerprintOverride: null # string + apiServer: + version: null # string + overrideAPIResources: null # [string] + extraAPIResources: null # [string] +system: + createSCCs: null # bool + enablePodSecurityPolicies: null # bool diff --git a/rhacs/4.3.8/secured-cluster-services/internal/defaults/00-bootstrap.yaml b/rhacs/4.3.8/secured-cluster-services/internal/defaults/00-bootstrap.yaml new file mode 100644 index 0000000..846ca57 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/defaults/00-bootstrap.yaml @@ -0,0 +1,15 @@ +# If we are being linted, magically apply settings that will not cause linting to break. +{{- if eq .Release.Name "test-release" }} +{{- include "srox.warn" (list . "You are using a release name that is reserved for tests. In order to allow linting to work, certain checks have been relaxed. If you are deploying to a real environment, we recommend that you choose a different release name.") }} +allowNonstandardNamespace: true +allowNonstandardReleaseName: true +clusterName: test-cluster-for-lint +{{- end }} +--- + +_namespace: {{ default .Release.Namespace ._rox.meta.namespaceOverride }} + +--- +meta: + useLookup: true + fileOverrides: {} diff --git a/rhacs/4.3.8/secured-cluster-services/internal/defaults/10-env.yaml b/rhacs/4.3.8/secured-cluster-services/internal/defaults/10-env.yaml new file mode 100644 index 0000000..48605ae --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/defaults/10-env.yaml @@ -0,0 +1,11 @@ +# This file applies default environment configuration, based on available API server resources. +{{- if kindIs "invalid" ._rox.env.istio }} +env: + {{- if has "networking.istio.io/v1alpha3" ._rox._apiServer.apiResources }} + istio: true + {{- include "srox.note" (list . "Based on API server properties, we have inferred that you are deploying into an Istio-enabled cluster. Set the `env.istio` property explicitly to false/true to override the auto-sensed value.") }} + {{- else }} + istio: false + {{- end }} +{{- end }} +system: diff --git a/rhacs/4.3.8/secured-cluster-services/internal/defaults/20-tls-files.yaml b/rhacs/4.3.8/secured-cluster-services/internal/defaults/20-tls-files.yaml new file mode 100644 index 0000000..6eb6408 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/defaults/20-tls-files.yaml @@ -0,0 +1,23 @@ +# These defaults ensure that by default, certificates and keys are loaded from the respective files in the secrets/ +# directory that they needed to be placed in for the old sensor Helm chart. +# +# A user can specify either references to files (with a "@" prefix - note that this requires changing the chart, +# as Helm only allows accessing files that are part of the chart), or PEM-encoded certificates and keys directly. + +ca: + cert: "@?secrets/ca.pem" + +sensor: + serviceTLS: + cert: "@?secrets/sensor-cert.pem" + key: "@?secrets/sensor-key.pem" + +admissionControl: + serviceTLS: + cert: "@?secrets/admission-control-cert.pem" + key: "@?secrets/admission-control-key.pem" + +collector: + serviceTLS: + cert: "@?secrets/collector-cert.pem" + key: "@?secrets/collector-key.pem" diff --git a/rhacs/4.3.8/secured-cluster-services/internal/defaults/30-base-config.yaml b/rhacs/4.3.8/secured-cluster-services/internal/defaults/30-base-config.yaml new file mode 100644 index 0000000..dcb4921 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/defaults/30-base-config.yaml @@ -0,0 +1,117 @@ +# This file contains basic configuration options for all services + +centralEndpoint: "central.{{ required "unknown namespace" ._rox._namespace }}.svc:443" +createUpgraderServiceAccount: false + +{{- if .Release.IsInstall }} +createSecrets: true +{{- end }} + +exposeMonitoring: false + +helmManaged: true + + +managedBy: MANAGER_TYPE_HELM_CHART + + +clusterName: "" +confirmNewClusterName: "" + +imagePullSecrets: + allowNone: true + useExisting: [] + useFromDefaultServiceAccount: true + +sensor: + endpoint: "sensor.{{ required "unknown namespace" ._rox._namespace }}.svc:443" + localImageScanning: + enabled: false + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Sensor is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + +admissionControl: + listenOnCreates: false + listenOnUpdates: false + listenOnEvents: {{ not ._rox.env.openshift }} + dynamic: + enforceOnCreates: false + scanInline: false + disableBypass: false + timeout: 20 + enforceOnUpdates: false + replicas: 3 + + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # node-role.kubernetes.io/master is replaced by node-role.kubernetes.io/control-plane from certain version + # of k8s. We apply both to be compatible with any k8s version. + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: Exists + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 60 + podAffinityTerm: + topologyKey: "kubernetes.io/hostname" + labelSelector: + matchLabels: + app: admission-control + +collector: + collectionMethod: "EBPF" + disableTaintTolerations: false + nodescanningEndpoint: "127.0.0.1:8444" + tolerations: + - operator: "Exists" + +auditLogs: + disableCollection: {{ ne ._rox.env.openshift 4 }} + +enableOpenShiftMonitoring: false +--- +sensor: + exposeMonitoring: {{ ._rox.exposeMonitoring }} +collector: + exposeMonitoring: {{ ._rox.exposeMonitoring }} +admissionControl: + exposeMonitoring: {{ ._rox.exposeMonitoring }} diff --git a/rhacs/4.3.8/secured-cluster-services/internal/defaults/40-resources.yaml b/rhacs/4.3.8/secured-cluster-services/internal/defaults/40-resources.yaml new file mode 100644 index 0000000..4dd0c19 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/defaults/40-resources.yaml @@ -0,0 +1,44 @@ +# This file contains the default resource requirements for the StackRox Secured Cluster services. + +sensor: + resources: + requests: + memory: "4Gi" + cpu: "2" + limits: + memory: "8Gi" + cpu: "4" + +admissionControl: + resources: + requests: + memory: "100Mi" + cpu: "50m" + limits: + memory: "500Mi" + cpu: "500m" + +collector: + resources: + requests: + memory: "320Mi" + cpu: "50m" + limits: + memory: "1Gi" + cpu: "750m" + + complianceResources: + requests: + memory: "10Mi" + cpu: "10m" + limits: + memory: "2Gi" + cpu: "1" + + nodeScanningResources: + requests: + memory: "10Mi" + cpu: "10m" + limits: + memory: "500Mi" + cpu: "1" diff --git a/rhacs/4.3.8/secured-cluster-services/internal/defaults/50-images.yaml b/rhacs/4.3.8/secured-cluster-services/internal/defaults/50-images.yaml new file mode 100644 index 0000000..e35acdc --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/defaults/50-images.yaml @@ -0,0 +1,114 @@ +# This file contains the default image (registry + name + tag) settings) for all StackRox Secured Cluster +# Services. + +# Initialize default meta values +image: + registry: registry.redhat.io/advanced-cluster-security + main: + name: rhacs-main-rhel8 + pullPolicy: IfNotPresent + collector: + name: rhacs-collector-rhel8 + slimName: rhacs-collector-slim-rhel8 + scanner: + name: rhacs-scanner-slim-rhel8 + tag: 4.3.8 + + scannerDb: + name: rhacs-scanner-db-slim-rhel8 + tag: 4.3.8 + +--- +# Add registry defaults +image: + main: + registry: {{ ._rox.image.registry }} + collector: + registry: {{ if or (eq ._rox.image.registry "stackrox.io") (eq ._rox.image.registry "registry.connect.redhat.com") }}collector.stackrox.io{{ else }}{{ ._rox.image.registry }}{{ end }} + scanner: + registry: {{ ._rox.image.registry }} + + scannerDb: + registry: {{ ._rox.image.registry }} + +--- +# Default to collector slim mode. If configured registry equals the default we can assume the cluster has internet connectivity. +collector: + slimMode: {{ eq ._rox.image.collector.registry "registry.redhat.io/advanced-cluster-security" }} +--- +# Configure repository (registry + name) +image: + main: + repository: {{ list ._rox.image.main.registry ._rox.image.main.name | compact | join "/" }} + collector: + {{- if ._rox.collector.slimMode }} + repository: {{ list ._rox.image.collector.registry ._rox.image.collector.slimName | compact | join "/" }} + {{- else }} + repository: {{ list ._rox.image.collector.registry ._rox.image.collector.name | compact | join "/" }} + {{- end }} + scanner: + repository: {{ list ._rox.image.scanner.registry ._rox.image.scanner.name | compact | join "/" }} + + scannerDb: + repository: {{ list ._rox.image.scannerDb.registry ._rox.image.scannerDb.name | compact | join "/" }} + +--- +# Configure collector slim image full ref +image: + collector: + {{- if and ._rox.collector.slimMode ._rox.image.collector.slim.fullRef }} + fullRef: {{ ._rox.image.collector.slim.fullRef }} + {{- else if and (not ._rox.collector.slimMode) ._rox.image.collector.full.fullRef }} + fullRef: {{ ._rox.image.collector.full.fullRef }} + {{- end }} +--- +# Apply fullRef and configurations to images +image: + main: + {{- if or ._rox.image.main.tag ._rox.image.main.fullRef }} + {{- include "srox.warn" (list . "You have specified an explicit main image (tag). This will prevent the main image from being updated correctly when upgrading to a newer version of this chart.") }} + {{- else }} + _abbrevImageRef: {{ ._rox.image.main.repository }} + {{- end }} + tag: 4.3.8 + collector: + {{- if or ._rox.image.collector.tag ._rox.image.collector.fullRef }} + {{- include "srox.warn" (list . "You have specified an explicit collector image tag. This will prevent the collector image from being updated correctly when upgrading to a newer version of this chart.") }} + {{- if ._rox.collector.slimMode }} + {{- include "srox.warn" (list . "You have specified an explicit collector image tag. The slim collector setting will not have any effect.") }} + {{- end }} + {{- else }} + _abbrevImageRef: {{ ._rox.image.collector.repository }} + {{- end }} +--- +# Configure tags and pull policies +image: + collector: + {{- if ._rox.collector.slimMode }} + tag: "4.3.8" + pullPolicy: IfNotPresent + {{- else }} + tag: "4.3.8" + pullPolicy: Always + {{- end }} +--- +# Add fullRef references to images +# TODO(ROX-9261): Add support for image pull policy to scanner slim +image: + main: + fullRef: {{ printf "%s:%s" ._rox.image.main.repository ._rox.image.main.tag }} + collector: + fullRef: {{ printf "%s:%s" ._rox.image.collector.repository ._rox.image.collector.tag }} + scanner: + fullRef: {{ printf "%s:%s" ._rox.image.scanner.repository ._rox.image.scanner.tag }} + + scannerDb: + fullRef: {{ printf "%s:%s" ._rox.image.scannerDb.repository ._rox.image.scannerDb.tag }} + +collector: + imagePullPolicy: {{ ._rox.image.collector.pullPolicy }} + complianceImagePullPolicy: {{ ._rox.image.main.pullPolicy }} +sensor: + imagePullPolicy: {{ ._rox.image.main.pullPolicy }} +admissionControl: + imagePullPolicy: {{ ._rox.image.main.pullPolicy }} diff --git a/rhacs/4.3.8/secured-cluster-services/internal/defaults/60-sccs.yaml b/rhacs/4.3.8/secured-cluster-services/internal/defaults/60-sccs.yaml new file mode 100644 index 0000000..36e74fd --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/defaults/60-sccs.yaml @@ -0,0 +1,2 @@ +system: + createSCCs: true diff --git a/rhacs/4.3.8/secured-cluster-services/internal/defaults/70-scanner.yaml b/rhacs/4.3.8/secured-cluster-services/internal/defaults/70-scanner.yaml new file mode 100644 index 0000000..43bc5d8 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/defaults/70-scanner.yaml @@ -0,0 +1,38 @@ +scanner: + disable: true + replicas: 3 + logLevel: INFO + mode: slim + + autoscaling: + disable: false + minReplicas: 2 + maxReplicas: 5 + + resources: + requests: + memory: "1500Mi" + cpu: "1000m" + limits: + memory: "4Gi" + cpu: "2000m" + + dbResources: + limits: + cpu: "2000m" + memory: "4Gi" + requests: + cpu: "200m" + memory: "200Mi" + + slimImage: + name: "" + tag: "" + fullRef: "" + repository: "" + + slimDBImage: + name: "" + tag: "" + fullRef: "" + repository: "" diff --git a/rhacs/4.3.8/secured-cluster-services/internal/defaults/whats-this.md b/rhacs/4.3.8/secured-cluster-services/internal/defaults/whats-this.md new file mode 100644 index 0000000..d58c8de --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/defaults/whats-this.md @@ -0,0 +1,39 @@ +`defaults/` directory +====================== + +This directory provides a set of files that provide a lighter-weight interface for configuring +defaults in the Helm chart, allowing the use of template expressions (including referencing previously +applied defaults) without requiring (an excessive amount of) template control structures (such as +`{{ if kindIs "invalid" ... }}` to determine if a value has already been set). + +After applying some "bootstrap" configuration (such as for making available API server resources +visible in a uniform manner), each `.yaml` file in this directory is processed in an order determined +by its name (hence the `NN-` prefixes). Each YAML file consists of multiple documents (separated by +`---` lines) that are rendered as templates and then _merged_ into the effective configuration, giving +strict preference to already set values. + +Having a deterministic order is important for being able to rely on previously configured +values (either specified by the user or applied as a default). For example, the file +```yaml +group: + setting: "foo" + anotherSetting: 3 +--- +group: + derivedSetting: {{ printf "%s-%d" ._rox.group.setting ._rox.group.anotherSetting }} +``` +combined with the command-line setting `--set group.setting=bar` will result in the following +"effective" configuration: +```yaml +group: + setting: "bar" # user-specified value takes precedence - default value "foo" not applied + anotherSetting: 3 # default value + derivedSetting: bar-3 # combination of user-specified value and default value; "pure" default without + # any --set arguments would be "foo-3" +``` + +**Caveats**: +- Templating instructions must be contained to a single document within the multi-document YAML files. In particular, + the `---` separator must not be within a conditionally rendered block, or emitted by templating code. +- It is recommended to contain dependencies between default settings to a single YAML file. While the `NN-` prefixes + ensure a well-defined application order of individual files, having dependent blocks in the same file adds clarity. diff --git a/rhacs/4.3.8/secured-cluster-services/internal/expandables.yaml b/rhacs/4.3.8/secured-cluster-services/internal/expandables.yaml new file mode 100644 index 0000000..09ebbae --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/expandables.yaml @@ -0,0 +1,44 @@ +imagePullSecrets: + username: true + password: true +mainImagePullSecrets: + username: true + password: true +collectorImagePullSecrets: + username: true + password: true +ca: + cert: true +sensor: + serviceTLS: + cert: true + key: true + resources: true + nodeSelector: true +admissionControl: + serviceTLS: + cert: true + key: true + resources: true + nodeSelector: true +collector: + serviceTLS: + cert: true + key: true + resources: true + complianceResources: true + nodeScanningResources: true + nodeSelector: true +scanner: + resources: true + dbResources: true + nodeSelector: true + dbNodeSelector: true + dbPassword: + value: true + serviceTLS: + cert: true + key: true + dbServiceTLS: + cert: true + key: true diff --git a/rhacs/4.3.8/secured-cluster-services/internal/scanner-config-shape.yaml b/rhacs/4.3.8/secured-cluster-services/internal/scanner-config-shape.yaml new file mode 100644 index 0000000..da3b315 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/internal/scanner-config-shape.yaml @@ -0,0 +1,40 @@ +scanner: + mode: null # string + disable: null # bool + replicas: null # int + logLevel: null # string + nodeSelector: null # string | dict + dbNodeSelector: null # string | dict + tolerations: null # [dict] + dbTolerations: null # [dict] + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + affinity: null # dict + resources: null # string | dict + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + dbImage: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + dbResources: null # string | dict + dbPassword: + value: null # string + generate: null # bool + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + dbServiceTLS: + cert: null # string + key: null # string + generate: null # bool + exposeMonitoring: null # bool +system: + enablePodSecurityPolicies: null # bool diff --git a/rhacs/4.3.8/secured-cluster-services/scripts/fetch-secrets.sh b/rhacs/4.3.8/secured-cluster-services/scripts/fetch-secrets.sh new file mode 100755 index 0000000..850a227 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/scripts/fetch-secrets.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# fetch-secrets.sh +# Retrieves StackRox TLS secrets currently stored in the current Kubernetes context, and stores them in a format +# suitable for consumption by the Helm chart. +# +# The YAML bundle is printed to stdout, use output redirection (>filename) to store the output to a file. +# This script supports the following environment variables: +# - KUBECTL: the command to use for kubectl. Spaces will be tokenized by the shell interpreter (default: "kubectl"). +# - ROX_NAMESPACE: the namespace in which the current StackRox deployment runs (default: "stackrox") +# - FETCH_CA_ONLY: if set to "true", will create a bundle containing only the CA certificate (default: "false") + +DIR="$(cd "$(dirname "$0")" && pwd)" + +KUBECTL="${KUBECTL:-kubectl}" +ROX_NAMESPACE="${ROX_NAMESPACE:-stackrox}" + +FETCH_CA_ONLY="${FETCH_CA_ONLY:-false}" + +case "$FETCH_CA_ONLY" in + false|0) + TEMPLATE_FILE="fetched-secrets-bundle.yaml.tpl" + DESCRIPTION="certificates and keys" + ;; + true|1) + TEMPLATE_FILE="fetched-secrets-bundle-ca-only.yaml.tpl" + DESCRIPTION="CA certificate only" + ;; + *) + echo >&2 "Invalid value '$FETCH_CA_ONLY' for FETCH_CA_ONLY, only false and true are allowed" + exit 1 +esac + +# The leading '#' signs aren't required as they don't go to stdout, but when printing to the console, +# it looks more natural to include them. +echo >&2 "# Fetching $DESCRIPTION from current Kubernetes context (namespace $ROX_NAMESPACE), store" +echo >&2 "# the output in a file and pass it to helm via the -f parameter." + +$KUBECTL get --ignore-not-found -n "$ROX_NAMESPACE" \ + secret/sensor-tls secret/collector-tls secret/admission-control-tls \ + -o go-template-file="${DIR}/${TEMPLATE_FILE}" \ diff --git a/rhacs/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl b/rhacs/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl new file mode 100644 index 0000000..b5a13c2 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl @@ -0,0 +1,9 @@ +{{- range $item := .items }} +{{- if eq $item.metadata.name "sensor-tls" }} +{{- $caPEM := index $item.data "ca.pem" }} +{{- if $caPEM }} +ca: + cert: "{{ $caPEM | base64decode | js }}" +{{- end }} +{{- end }} +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl b/rhacs/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl new file mode 100644 index 0000000..72bb452 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl @@ -0,0 +1,35 @@ +{{- range $item := .items }} +{{- if eq $item.metadata.name "sensor-tls" }} +{{- $caPEM := index $item.data "ca.pem" }} +{{- if $caPEM }} +ca: + cert: "{{ $caPEM | base64decode | js }}" +{{- end }} +{{- $sensorCert := index $item.data "sensor-cert.pem" }} +{{- $sensorKey := index $item.data "sensor-key.pem" }} +{{- if and $sensorCert $sensorKey }} +sensor: + serviceTLS: + cert: "{{ $sensorCert | base64decode | js }}" + key: "{{ $sensorKey | base64decode | js }}" +{{- end }} +{{- else if eq $item.metadata.name "collector-tls" }} +{{- $collectorCert := index $item.data "collector-cert.pem" }} +{{- $collectorKey := index $item.data "collector-key.pem" }} +{{- if and $collectorCert $collectorKey }} +collector: + serviceTLS: + cert: "{{ $collectorCert | base64decode | js }}" + key: "{{ $collectorKey | base64decode | js }}" +{{- end }} +{{- else if eq $item.metadata.name "admission-control-tls" }} +{{- $admCtrlCert := index $item.data "admission-control-cert.pem" }} +{{- $admCtrlKey := index $item.data "admission-control-key.pem" }} +{{- if and $admCtrlCert $admCtrlKey }} +admissionControl: + serviceTLS: + cert: "{{ $admCtrlCert | base64decode | js }}" + key: "{{ $admCtrlKey | base64decode | js }}" +{{- end }} +{{- end }} +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/sensor-chart-upgrade.md b/rhacs/4.3.8/secured-cluster-services/sensor-chart-upgrade.md new file mode 100644 index 0000000..615a03a --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/sensor-chart-upgrade.md @@ -0,0 +1,159 @@ +# Upgrading from the `sensor` Helm chart + +There are differences between the `sensor` Helm chart that was part of the +StackRox Kubernetes Security Platform version 3.0.54 and the Secured Cluster +Services Helm chart in the StackRox Kubernetes Security Platform version 3.0.55. + +Therefore, if you are using the StackRox Kubernetes Security Platform version 3.0.54 +or older, and you've used the `sensor` Helm chart, you must verify (and change) +the following additional options to upgrade to the new Helm charts for the +StackRox Kubernetes Security Platform version 3.0.55. + +## Namespace + +|Version 3.0.54 and older |Version 3.0.55 and newer | +|-------------------------|-------------------------| +|The `sensor` Helm chart creates all Kubernetes resources in the `stackrox` namespace, even if you've used the `-n`/`--namespace` flag to the `helm install` command.|The Secured Cluster Services Helm chart creates all resources in the namespace you specify by using the `-n`/`--namespace` flag. However, we recommend that you always install the chart in the `stackrox` namespace.| + +If you've previously installed the `sensor` Helm chart into a namespace other +than `stackrox`, you **must** set the namespace override option to `stackrox`. + +To do this, either: +- pass the `--set meta.namespaceOverride=stackrox` flag, or +- add the following section in your configuration file: + ```yaml + meta: + namespaceOverride: stackrox + ``` + +## Configuration file + +|Version 3.0.54 and older |Version 3.0.55 and newer | +|-------------------------|--------------------------| +|Installation using the `sensor` Helm chart requires adding your customizations in the `values.yaml` file that is part of the chart.|The Secured Cluster Services Helm chart uses a separate configuration file.| + +> **IMPORTANT** +> +> If you are using the Secured Cluster Services Helm chart, **do not** modify +> the `values.yaml` file that is part of the chart. + +We recommend that you always store the configuration in separate files: + +- `values-public.yaml`: include all non-sensitive configuration options in this + file. +- `values-private.yaml`: include all sensitive configuration options such as + image pull secrets or certificates and keys. + +You can also use a separate file for the cluster init bundle. For more +information, see the main [README.md](README.md) file. + +## Secrets injection + +|Version 3.0.54 and older |Version 3.0.55 and newer | +|-------------------------|--------------------------| +|The `sensor` Helm chart downloads certificates and private keys specific to a single cluster and stores them in the `secrets/` directory.|The Secured Cluster Services Helm chart uses cluster init bundles. For more information, see the main [README.md](README.md) file.| + +To upgrade, +1. Copy the `values.yaml` you used for the most recent installation or upgrade of the + `sensor` Helm chart and store it as `sensor-values.yaml`. +1. Connect to the Kubernetes cluster on which you've previously installed the + `sensor` Helm chart. +1. Run `./scripts/fetch-secrets.sh`. The `fetch-secrets.sh` script shows a YAML + file as output, which contains all secrets. Store the output of this command + in a file (you can use `./scripts/fetch-secrets.sh >secrets.yaml` to directly + write the command output to a file called `secrets.yaml`). +1. Run the `helm upgrade` command and pass the YAML (from the previous step) file by + using the `-f` option: + ```sh + helm upgrade -n stackrox sensor stackrox/secured-cluster-services \ + --reuse-values -f sensor-values.yaml -f ... + ``` + The above command assumes that you have added the https://mirror.openshift.com/pub/rhacs/charts Helm + chart repository to your local Helm installation. See the main [README.md](README.md) + for instructions on how to set this up. + If you want to use this chart from a local directory, replace + `stackrox/secured-cluster-services` with the path to the chart directory. + +> **NOTE** +> +> Although you can copy the `secrets` directory from your old `sensor` Helm +> chart instead, we **do not** recommend doing it. + + +## Helm-managed clusters + +When you use the Secured Cluster Services Helm chart, the clusters it creates +are treated as Helm-managed by default. It means that whenever you run the +`helm upgrade` command afterward, it applies the configuration changes specified +in your Helm configuration file, overwriting any changes to settings you've done +through the StackRox portal. + +Additionally, because of the differences between the Helm upgrade and the +StackRox Kubernetes Security Platform automatic upgrade, you can't use +the automatic upgrades option from the StackRox portal. + +If you don't want an upgraded cluster to be treated as Helm-managed, set the +`helmManaged` configuration option to `false`. + +## Configuration format + +There are differences between the configuration format that the sensor Helm +chart uses and the Secured Cluster Services Helm chart's uses. We recommend that +you migrate to the new configuration format. + +Here is the list of old and new configuration options: + +|Old configuration option |New configuration option | +|-------------------------|-------------------------| +| `cluster.name` | `clusterName` | +| `cluster.type` | Set `env.openshift` to `true` for `cluster.type=OPENSHIFT_CLUSTER` and `false` for `cluster.type=KUBERNETES_CLUSTER`. Leave unset to automatically detect (recommended). | +| `endpoint.central` | `centralEndpoint` | +| `endpoint.advertised` | `sensor.endpoint` | +| `image.repository.main` | `image.main.name` | +| `image.repository.collector` | `image.collector.name` | +| `image.registry.main` | `image.main.registry` | +| `image.registry.collector` | `image.collector.registry` | +| `image.pullPolicy.main` | `image.main.pullPolicy` | +| `image.pullPolicy.collector` | `image.collector.pullPolicy` | +| `image.tag.main` | `image.main.tag` | +| `image.tag.collector` | `image.collector.tag` | +| `config.collectionMethod` | `collector.collectionMethod` | +| `config.admissionControl.createService` | `admissionControl.listenOnCreates` | +| `config.admissionControl.listenOnUpdates` | `admissionControl.listenOnUpdates` | +| `config.admissionControl.enableService` | `admissionControl.dynamic.enforceOnCreates` | +| `config.admissionControl.enforceOnUpdates` | `admissionControl.dynamic.enforceOnUpdates` | +| `config.admissionControl.scanInline` | `admissionControl.dynamic.scanInline` | +| `config.admissionControl.disableBypass` | `admissionControl.dynamic.disableBypass` | +| `config.admissionControl.timeout` | `admissionControl.dynamic.timeout` | +| `config.registryOverride` | `registryOverride` | +| `config.disableTaintTolerations` | `collector.disableTaintTolerations` | +| `config.createUpgraderServiceAccount` | `createUpgraderServiceAccount` | +| `config.createSecrets` | `createSecrets` | +| `config.offlineMode` | This option has no effect and will be removed. | +| `config.slimCollector` | `collector.slimMode` | +| `config.sensorResources` | `sensor.resources` | +| `config.admissionControlResources` | `admissionControl.resources` | +| `config.collectorResources` | `collector.resources` | +| `config.complianceResources` | `collector.complianceResources` | +| `config.exposeMonitoring` | `exposeMonitoring` | +| `envVars` | See example below | + +**Custom environment variables:** The old format for custom environment variable settings was +```yaml +envVars: +- name: ENV_VAR1 + value: "value1" +- name: ENV_VAR2 + value: "value2" +... +``` + +In the new configuration format, rewrite this as: +```yaml +customize: + envVars: + ENV_VAR1: "value1" + ENV_VAR2: "value2" +``` +You can find out more about customizing object labels, annotations, and environment variables in the main +[README.md](README.md). \ No newline at end of file diff --git a/rhacs/4.3.8/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml b/rhacs/4.3.8/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml new file mode 100644 index 0000000..eba103f --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.collectorImagePullSecrets._dockerAuths }} +apiVersion: v1 +kind: Secret +type: kubernetes.io/dockerconfigjson +metadata: + name: secured-cluster-services-collector + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "secured-cluster-services-collector") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "secured-cluster-services-collector") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +data: + .dockerconfigjson: {{ dict "auths" ._rox.collectorImagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/00-injected-ca-bundle.yaml b/rhacs/4.3.8/secured-cluster-services/templates/00-injected-ca-bundle.yaml new file mode 100644 index 0000000..3289c2a --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/00-injected-ca-bundle.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} + +{{- if eq ._rox.env.openshift 4 }} +{{ $injectedCABundleName := printf "injected-cabundle-%s" .Release.Name }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $injectedCABundleName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" $injectedCABundleName) | nindent 4 }} + "config.openshift.io/inject-trusted-cabundle": "true" + annotations: + {{- include "srox.annotations" (list . "configmap" $injectedCABundleName) | nindent 4 }} +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/00-main-image-pull-secrets.yaml b/rhacs/4.3.8/secured-cluster-services/templates/00-main-image-pull-secrets.yaml new file mode 100644 index 0000000..052aa3e --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/00-main-image-pull-secrets.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.mainImagePullSecrets._dockerAuths }} +apiVersion: v1 +kind: Secret +type: kubernetes.io/dockerconfigjson +metadata: + name: secured-cluster-services-main + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "secured-cluster-services-main") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "secured-cluster-services-main") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +data: + .dockerconfigjson: {{ dict "auths" ._rox.mainImagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml new file mode 100644 index 0000000..a27c602 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "scanner") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} + +{{ end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-01-psps.yaml b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-01-psps.yaml new file mode 100644 index 0000000..23b398c --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-01-psps.yaml @@ -0,0 +1,69 @@ +{{- include "srox.init" . -}} + +{{- if and (not ._rox.scanner.disable) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-scanner-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-scanner-psp") | nindent 4 }} +rules: +- apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-scanner-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-scanner-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-scanner-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-psp") }} +subjects: + - kind: ServiceAccount + name: scanner + namespace: {{ .Release.Namespace }} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-scanner") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-01-security.yaml b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-01-security.yaml new file mode 100644 index 0000000..3c1d92b --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-01-security.yaml @@ -0,0 +1,78 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable }} +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner") }} + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-scanner") | nindent 4 }} + kubernetes.io/description: stackrox-scanner is the security constraint for the Scanner container +priority: 0 +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +users: + - system:serviceaccount:{{ .Release.Namespace }}:scanner +volumes: + - '*' +allowHostDirVolumePlugin: false +allowedCapabilities: [] +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +defaultAddCapabilities: [] +fsGroup: + type: RunAsAny +readOnlyRootFilesystem: false +requiredDropCapabilities: [] + +{{- else if eq ._rox.env.openshift 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-scanner-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-scanner-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-scanner-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - anyuid + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: scanner-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "scanner-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "scanner-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-scanner-scc +subjects: +- kind: ServiceAccount + name: scanner + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml new file mode 100644 index 0000000..c6c0bc1 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml @@ -0,0 +1,27 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if ._rox.scanner._dbPassword -}} +{{- if not (kindIs "invalid" ._rox.scanner._dbPassword.value) -}} + +apiVersion: v1 +kind: Secret +metadata: + name: scanner-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.scanner._dbPassword.value | nindent 4 }} + +{{- end -}} +{{- end -}} + +{{ end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml new file mode 100644 index 0000000..4ed16c7 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml @@ -0,0 +1,18 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner/config.yaml.tpl") . | nindent 4 }} + +{{ end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-05-network-policy.yaml b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-05-network-policy.yaml new file mode 100644 index 0000000..99f7233 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-05-network-policy.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner + ingress: + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP +{{ if or (eq ._rox.scanner.mode "slim") ._rox.env.openshift }} + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP +{{ end }} + policyTypes: + - Ingress + +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-db") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-db + ingress: + - from: + - podSelector: + matchLabels: + app: scanner + ports: + - port: 5432 + protocol: TCP + policyTypes: + - Ingress + +{{ end -}} + +{{ if ._rox.scanner.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: scanner + policyTypes: + - Ingress +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-06-deployment.yaml b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-06-deployment.yaml new file mode 100644 index 0000000..89ac82c --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-06-deployment.yaml @@ -0,0 +1,296 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + app: scanner + {{- include "srox.labels" (list . "deployment" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner") | nindent 4 }} +spec: + replicas: {{ ._rox.scanner.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner + {{- include "srox.podLabels" (list . "deployment" "scanner") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8080,8443" + {{- include "srox.podAnnotations" (list . "deployment" "scanner") | nindent 8 }} + spec: + {{- if ._rox.scanner._nodeSelector }} + nodeSelector: + {{- ._rox.scanner._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.tolerations }} + tolerations: + {{- toYaml ._rox.scanner.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scanner.affinity | nindent 8 }} + containers: + - name: scanner + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimImage.fullRef | quote }} + {{ else }} + image: {{ ._rox.scanner.image.fullRef | quote }} + {{ end -}} + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if ._rox.env.openshift }} + - name: ROX_OPENSHIFT_API + value: "true" + {{- end}} + {{- include "srox.envVars" (list . "deployment" "scanner" "scanner") | nindent 8 }} + resources: + {{- ._rox.scanner._resources | nindent 10 }} + command: + - /entrypoint.sh + ports: + - name: https + containerPort: 8080 + - name: grpc + containerPort: 8443 + {{ if ._rox.scanner.exposeMonitoring -}} + - name: monitoring + containerPort: 9090 + {{- end}} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /scanner/ping + port: 8080 + timeoutSeconds: 10 + periodSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + volumeMounts: + - name: scanner-etc-ssl-volume + mountPath: /etc/ssl + - name: scanner-etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: scanner-config-volume + mountPath: /etc/scanner + readOnly: true + - name: scanner-tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: vuln-temp-db + mountPath: /var/lib/stackrox + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: scanner-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner + volumes: + - name: additional-ca-volume + secret: + defaultMode: 420 + optional: true + secretName: additional-ca + - name: scanner-etc-ssl-volume + emptyDir: {} + - name: scanner-etc-pki-volume + emptyDir: {} + - name: scanner-config-volume + configMap: + name: scanner-config + - name: scanner-tls-volume + secret: + secretName: scanner-tls + - name: vuln-temp-db + emptyDir: {} + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: scanner-db-password + secret: + secretName: scanner-db-password + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + app: scanner-db + {{- include "srox.labels" (list . "deployment" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-db + {{- include "srox.podLabels" (list . "deployment" "scanner-db") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "5432" + {{- include "srox.podAnnotations" (list . "deployment" "scanner-db") | nindent 8 }} + spec: + {{- if ._rox.scanner._dbNodeSelector }} + nodeSelector: + {{- ._rox.scanner._dbNodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.dbTolerations }} + tolerations: + {{- toYaml ._rox.scanner.dbTolerations | nindent 8 }} + {{- end }} + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # ScannerDB is single-homed, so avoid preemptible nodes. + - weight: 100 + preference: + matchExpressions: + - key: cloud.google.com/gke-preemptible + operator: NotIn + values: + - "true" + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/infra + operator: Exists + - weight: 25 + preference: + matchExpressions: + - key: node-role.kubernetes.io/compute + operator: Exists + # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in + # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist + initContainers: + - name: init-db + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimDBImage.fullRef | quote }} + {{ else -}} + image: {{ ._rox.scanner.dbImage.fullRef | quote }} + {{ end -}} + env: + - name: POSTGRES_PASSWORD_FILE + value: "/run/secrets/stackrox.io/secrets/password" + - name: ROX_SCANNER_DB_INIT + value: "true" + resources: + {{- ._rox.scanner._dbResources | nindent 12 }} + volumeMounts: + - name: scanner-db-data + mountPath: /var/lib/postgresql/data + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + readOnly: true + - name: scanner-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + containers: + - name: db + {{ if eq ._rox.scanner.mode "slim" -}} + image: {{ ._rox.scanner.slimDBImage.fullRef | quote }} + {{ else -}} + image: {{ ._rox.scanner.dbImage.fullRef | quote }} + {{ end -}} + env: + {{- include "srox.envVars" (list . "deployment" "scanner-db" "db") | nindent 10 }} + ports: + - name: tcp-postgresql + protocol: TCP + containerPort: 5432 + resources: + {{- ._rox.scanner._dbResources | nindent 10 }} + volumeMounts: + - name: scanner-db-data + mountPath: /var/lib/postgresql/data + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + readOnly: true + serviceAccountName: scanner + securityContext: + fsGroup: 70 + runAsGroup: 70 + runAsNonRoot: true + runAsUser: 70 + volumes: + - name: scanner-config-volume + configMap: + name: scanner-config + - name: scanner-tls-volume + secret: + secretName: scanner-tls + - name: scanner-db-tls-volume + secret: + secretName: scanner-db-tls + defaultMode: 0640 + items: + - key: cert.pem + path: server.crt + - key: key.pem + path: server.key + - key: ca.pem + path: root.crt + - name: scanner-db-data + emptyDir: {} + - name: scanner-db-password + secret: + secretName: scanner-db-password + +{{ end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-07-service.yaml b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-07-service.yaml new file mode 100644 index 0000000..2f65b15 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-07-service.yaml @@ -0,0 +1,99 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +apiVersion: v1 +kind: Service +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner") | nindent 4 }} +spec: + ports: + - name: https-scanner + port: 8080 + targetPort: 8080 + - name: grpcs-scanner + port: 8443 + targetPort: 8443 + {{ if ._rox.scanner.exposeMonitoring -}} + - name: monitoring + port: 9090 + targetPort: monitoring + {{- end}} + selector: + app: scanner + type: ClusterIP + +--- + +apiVersion: v1 +kind: Service +metadata: + name: scanner-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-db") | nindent 4 }} +spec: + ports: + - name: tcp-db + port: 5432 + targetPort: 5432 + selector: + app: scanner-db + type: ClusterIP + +{{ if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for ports 8080 and 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8080 + tls: + mode: DISABLE + - port: + number: 8443 + tls: + mode: DISABLE + +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-db-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-db-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 5432, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-db-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-db.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 5432 + tls: + mode: DISABLE +{{ end }} + +{{ end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-08-hpa.yaml b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-08-hpa.yaml new file mode 100644 index 0000000..c7af476 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/02-scanner-08-hpa.yaml @@ -0,0 +1,25 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable -}} + +{{- if not ._rox.scanner.autoscaling.disable -}} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scanner.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scanner.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner + targetCPUUtilizationPercentage: 150 +{{ end -}} + +{{ end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/NOTES.txt b/rhacs/4.3.8/secured-cluster-services/templates/NOTES.txt new file mode 100644 index 0000000..9c9fd01 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/NOTES.txt @@ -0,0 +1,40 @@ +{{- $_ := include "srox.init" . -}} + +StackRox Secured Cluster Services {{.Chart.AppVersion}} has been installed. + + +Secured Cluster Configuration Summary: + + Name: {{ ._rox.clusterName }} + Kubernetes Namespace: {{ ._rox._namespace }}{{ if ne .Release.Namespace ._rox._namespace }} [NOTE: Helm release is attached to namespace {{ .Release.Namespace }}]{{ end }} + Helm Release Name: {{ .Release.Name }} + Central Endpoint: {{ ._rox.centralEndpoint }} + OpenShift Cluster: {{ if eq ._rox.env.openshift 0 -}} false {{ else -}} {{ ._rox.env.openshift }} {{ end }} + Admission Control Webhooks deployed: {{ or ._rox.admissionControl.dynamic.listenOnCreates ._rox.admissionControl.dynamic.listenOnUpdates ._rox.admissionControl.dynamic.listenOnEvents}} + Admission Control Creates/Updates enforced: {{ or ._rox.admissionControl.dynamic.enforceOnCreates ._rox.admissionControl.dynamic.enforceOnUpdates }} + +{{ if ._rox._state.notes -}} +Please take note of the following: +{{ range ._rox._state.notes }} +- {{ . | wrapWith 98 "\n " -}} +{{ end }} + +{{ end -}} + +{{ if ._rox._state.warnings -}} +During installation, the following warnings were encountered: +{{ range ._rox._state.warnings }} +- WARNING: {{ . | wrapWith 98 "\n " -}} +{{ end }} + +{{ end -}} + +{{ if ._rox.env.openshift -}} +IMPORTANT: You have deployed into an OpenShift-enabled cluster. If you see that your pods + are not scheduling, run + + oc annotate namespace/{{ ._rox._namespace }} --overwrite openshift.io/node-selector="" +{{ end -}} + + +Thank you for using StackRox! diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_compatibility.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_compatibility.tpl new file mode 100644 index 0000000..c83ab2d --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_compatibility.tpl @@ -0,0 +1,51 @@ +{{ define "srox.applyCompatibilityTranslation" }} +{{ $ := index . 0 }} +{{ $values := index . 1 }} +{{ $translationRules := $.Files.Get "internal/compatibility-translation.yaml" | fromYaml }} +{{ include "srox._doApplyCompat" (list $values $.Template $values $translationRules list) }} +{{ end }} + +{{ define "srox._doApplyCompat" }} +{{ $values := index . 0 }} +{{ $template := index . 1 }} +{{ $valuesCtx := index . 2 }} +{{ $ruleCtx := index . 3 }} +{{ $ctxPath := index . 4 }} +{{ range $k, $v := $ruleCtx }} + {{ $oldVal := index $valuesCtx $k }} + {{ if not (kindIs "invalid" $oldVal) }} + {{ if kindIs "map" $v }} + {{ if kindIs "map" $oldVal }} + {{ include "srox._doApplyCompat" (list $values $template $oldVal $v (append $ctxPath $k)) }} + {{ if not $oldVal }} + {{ $_ := unset $valuesCtx $k }} + {{ end }} + {{ end }} + {{ else }} + {{ $_ := unset $valuesCtx $k }} + {{ if not (kindIs "invalid" $v) }} + {{ $tplCtx := dict "Template" $template "value" (toJson $oldVal) "rawValue" $oldVal }} + {{ $configFragment := tpl $v $tplCtx | fromYaml }} + {{ include "srox._mergeCompat" (list $values $configFragment (append $ctxPath $k) list) }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{ define "srox._mergeCompat" }} +{{ $values := index . 0 }} +{{ $newConfig := index . 1 }} +{{ $compatValuePath := index . 2 }} +{{ $path := index . 3 }} +{{ range $k, $v := $newConfig }} + {{ $currVal := index $values $k }} + {{ if kindIs "invalid" $currVal }} + {{ $_ := set $values $k $v }} + {{ else if and (kindIs "map" $v) (kindIs "map" $currVal) }} + {{ include "srox._mergeCompat" (list $currVal $v $compatValuePath (append $path $k)) }} + {{ else }} + {{ include "srox.fail" (printf "Conflict between legacy configuration values %s and explicitly set configuration value %s, please unset legacy value" (join "." $compatValuePath) (append $path $k | join ".")) }} + {{ end }} +{{ end }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_crypto.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_crypto.tpl new file mode 100644 index 0000000..1455288 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_crypto.tpl @@ -0,0 +1,239 @@ +{{/* + srox.configureCrypto $ $cryptoConfigPath $spec + + This helper function configures a private key or certificate (public cert + private key) + config entry, from an input config which is accessed via $cryptoConfigPath relative to + $._rox, which we'll refer to as $inputCfg. $inputCfg is expected to be a dict with at + least `key` and `generate` properties. If `generate` is null, it defaults to either `true` + on installations, and `false` on upgrades. `key` is an expandable string. + The result in either mode is written to a dict $outputCfg under $._rox accessed by the + $cryptoConfigPath, with a '_' prepended to the last path element. E.g., if + $cryptoConfigPath is "a.b.c", the input configuration will be read from $._rox.a.b.c, and + the output configuration will be stored in $._rox.a.b._c. + + Private key-only mode is selected if $spec.keyOnly contains a non-zero string, which specifies + the key algorithm to use. In this mode, if $inputCfg.key expands to a non-empty string, this + string will be copied to the `Key` property of $outputCfg. Otherwise, if $inputCfg.generate + is true (wrt. the above defaulting rules), a key with the algorithm prescribed by $spec.keyOnly + will be generated and stored in the `Key` property of $outputCfg. + + Certificate mode is the default. If $inputCfg.cert and $inputCfg.key expand to non-empty strings, + these strings will be copied to the `Cert` and `Key` properties of $outputCfg. Otherwise, if both + of them expand to empty strings (it is an error if only one of them expands to a non-empty + string), and $inputCfg.generate is true, a certificate and private key are generated with the + following options: + - If $inputCfg.ca is true, generate a CA certificate with common name $inputCfg.CN and a 5 year + validity duration. + - Otherwise, generate a leaf certificate with common name $inputCfg.CN and a 1 year validity + duration. The SANs for this certificate are derived from the base DNS name $inputCfg.dnsBase + according to "srox.computeSANs". + + Whenever certificates and/or private keys were generated, the $._rox._state.generated property + is updated to reflect the generated values, such that merging $._rox._state.generated in to + $.Values would have caused this template to simply use the generated values as-is. E.g., if + $cryptoConfigPath was "a.b.c" and $.Values.a.b.c.cert" and $.Values.a.b.c.key" were both empty, + $._rox._state.generated.a.b.c would be set to be a dict with `cert` and `key` properties of the + generated $outputCfg.Cert and $outputCfg.Key. + + If a certificate or private key was generated, $._rox._state.customCertGen is set to true. + */}} +{{- define "srox.configureCrypto" -}} +{{ $ := index . 0 }} +{{ $cryptoConfigPath := index . 1 }} +{{ $spec := index . 2 }} + +{{/* Resolve $cryptoConfigPath. */}} +{{ $cfg := $._rox }} +{{ $newGenerated := dict }} +{{ $genCfg := $newGenerated }} +{{ $cryptoConfigPathList := splitList "." $cryptoConfigPath }} +{{ range $pathElem := $cryptoConfigPathList }} + {{ $cfg = index $cfg $pathElem }} + {{ $newCfg := dict }} + {{ $_ := set $genCfg $pathElem $newCfg }} + {{ $genCfg = $newCfg }} +{{ end }} + +{{/* Make sure `cert` and `key` are expanded (this should already be the case, but better + safe than sorry. */}} +{{ $certExpandSpec := dict "cert" true "key" true }} +{{ include "srox.expandAll" (list $ $cfg $certExpandSpec $cryptoConfigPathList) }} + +{{ $certPEM := $cfg._cert }} +{{ $keyPEM := $cfg._key }} + +{{ $result := dict }} +{{ if $certPEM }} + {{ $result = dict "Cert" $certPEM "Key" (default "" $keyPEM) }} +{{ else if or $certPEM $keyPEM }} + {{ if and $keyPEM $spec.keyOnly }} + {{ $_ := set $result "Key" $keyPEM }} + {{ else }} + {{ include "srox.fail" (printf "Either none or both of %s.cert and %s.key must be specified" $cryptoConfigPath $cryptoConfigPath) }} + {{ end }} +{{ else }} + {{ $generate := $cfg.generate }} + {{ if kindIs "invalid" $generate }} + {{ $generate = $.Release.IsInstall }} + {{ end }} + {{ if $generate }} + {{ if $spec.ca }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"ca\" (genCA .cn 1825) }}" (dict "Template" $.Template "cn" $spec.CN "out" $out) }} + {{ $result = $out.ca }} + {{ else if $spec.keyOnly }} + {{ $key := tpl "{{ genPrivateKey .algo }}" (dict "Template" $.Template "algo" $spec.keyOnly) }} + {{ $_ := set $genCfg "key" $key }} + {{ $_ = set $result "Key" $key }} + {{ else }} + {{ if not $._rox._ca }} + {{ include "srox.fail" (printf "Tried to generate certificate for %s, but no CA certificate is available." $spec.CN) }} + {{ end }} + {{ $sans := dict }} + {{ include "srox.computeSANs" (list $ $sans $spec.dnsBase) }} + {{ $ca := $._rox._ca }} + {{ if kindIs "map" $ca }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"ca\" (buildCustomCert (b64enc .ca.Cert) (b64enc .ca.Key)) }}" (dict "Template" $.Template "ca" $ca "out" $out) }} + {{ $ca = $out.ca }} + {{ end }} + {{ $out := dict }} + {{ $_ := tpl "{{ $_ := set .out \"cert\" (genSignedCert .cn nil .sans 365 .ca) }}" (dict "Template" $.Template "cn" $spec.CN "sans" $sans.result "ca" $ca "out" $out) }} + {{ $result = $out.cert }} + {{ $_ := set $genCfg "cert" $result.Cert }} + {{ $_ = set $genCfg "key" $result.Key }} + {{ end }} + {{ $_ := set $genCfg "key" $result.Key }} + {{ if $result.Cert }} + {{ $_ = set $genCfg "cert" $result.Cert }} + {{ end }} + {{ $_ = set $._rox._state "customCertGen" true }} + {{ end }} +{{ end }} + +{{/* Store output configuration and generated properties */}} +{{ $newCfgRoot := dict }} +{{ $newCfg := $newCfgRoot }} +{{ range $pathElem := initial $cryptoConfigPathList }} + {{ $nextCfg := dict }} + {{ $_ := set $newCfg $pathElem $nextCfg }} + {{ $newCfg = $nextCfg }} +{{ end }} +{{ $_ := set $newCfg (last $cryptoConfigPathList | printf "_%s") $result }} +{{ $_ = include "srox.mergeInto" (list $._rox $newCfgRoot) }} +{{ $_ = include "srox.mergeInto" (list $._rox._state.generated $newGenerated) }} +{{ end }} + + +{{/* + srox.configurePassword $ $pwConfigPath [$htpasswdUser] + + This helper function reads a password configuration (YAML dict with `value` + and `generate` properties) referenced by $pwConfigPath relative to $._rox. It + ensures the dict with the same config path relative to $._rox and prepending an underscore + to the last path element is populated in the following way: + - If the `value` property of the input config is nonzero, set `value` in the result to the + expanded value. + - If the optional $htpasswdUser parameter is specified and the `htpasswd` property of the + input config is nonzero, set `htpasswd` in the result to the expanded value of that + property. + - If none of the above (non-mutually-exclusive) cases apply: + - If `generate` is true OR both `generate` is null and this is an installation, + not an upgrade, generate a random password with 32 alphanumeric characters. + - Otherwise, leave the result property empty. + - If the optional $htpasswdUser parameter was specified AND the `value` property in the + result property was set per the above rules AND the `htpasswd` property was not set, + populate the `htpasswd` property of the result by generating an htpasswd stanza with + the computed `value` as the password and $htpasswdUser as the username. + + The $._rox._state.generated property is adjusted accordingly. + */}} +{{- define "srox.configurePassword" -}} +{{ $ := index . 0 }} +{{ $pwConfigPath := index . 1 }} +{{ $htpasswdUser := "" }} +{{ if gt (len .) 2 }} + {{ $htpasswdUser = index . 2 }} +{{ end }} +{{ $cfg := $._rox }} +{{ $newGenerated := dict }} +{{ $genCfg := $newGenerated }} +{{ $pwConfigPathList := splitList "." $pwConfigPath }} +{{ range $pathElem := $pwConfigPathList }} + {{ $cfg = index $cfg $pathElem }} + {{ $newCfg := dict }} + {{ $_ := set $genCfg $pathElem $newCfg }} + {{ $genCfg = $newCfg }} +{{ end }} + +{{/* Make sure that `value` and `htpasswd` within $cfg are expanded (this should already be the + case but better safe than sorry). */}} +{{ $pwExpandSpec := dict "value" true "htpasswd" true }} +{{ include "srox.expandAll" (list $ $cfg $pwExpandSpec $pwConfigPathList) }} + +{{ $result := dict }} +{{ if and $htpasswdUser (not (kindIs "invalid" $cfg._htpasswd)) }} + {{ $htpasswd := $cfg._htpasswd }} + {{ $_ := set $result "htpasswd" $htpasswd }} +{{ end }} +{{ if not $result.htpasswd }} + {{ $pw := dict.nil }} + {{ if kindIs "invalid" $cfg._value }} + {{ $generate := $cfg.generate }} + {{ if kindIs "invalid" $generate }} + {{ $generate = $.Release.IsInstall }} + {{ end }} + {{ if $generate }} + {{ $pw = randAlphaNum 32 }} + {{ $_ := set $genCfg "value" $pw }} + {{ end }} + {{ else }} + {{ $pw = $cfg._value }} + {{ end }} + {{ if not (kindIs "invalid" $pw) }} + {{ $_ := set $result "value" $pw }} + {{ end }} + {{ if and $htpasswdUser $pw }} + {{ $htpasswd := tpl "{{ htpasswd .user .pw }}" (dict "Template" $.Template "user" $htpasswdUser "pw" $pw) }} + {{ $_ := set $result "htpasswd" $htpasswd }} + {{ end }} +{{ else if $cfg.value }} + {{ include "srox.fail" (printf "Both a htpasswd and a value are specified for %s, this is illegal. Remove the `value` property, or ensure that `htpasswd` is null." $pwConfigPath) }} +{{ end }} +{{ $newCfgRoot := dict }} +{{ $newCfg := $newCfgRoot }} +{{ range $pathElem := initial $pwConfigPathList }} + {{ $nextCfg := dict }} + {{ $_ := set $newCfg $pathElem $nextCfg }} + {{ $newCfg = $nextCfg }} +{{ end }} +{{ $_ := set $newCfg (last $pwConfigPathList | printf "_%s") $result }} +{{ $_ = include "srox.mergeInto" (list $._rox $newCfgRoot) }} +{{ $_ = include "srox.mergeInto" (list $._rox._state.generated $newGenerated) }} +{{ end }} + + +{{/* + srox.computeSANs $ $out $svcName + + Compute the applicable SANs for a service with name $svcName, deployed in namespace + $.Release.Namespace (= $releaseNS). + Generally, SANs following the pattern "$svcName.$releaseNS[.svc[.cluster.local]]" will be + generated. If $releaseNS is not "stackrox", another set of SANs with the same pattern, + but assuming $releaseNS = "stackrox", will be generated in addition. + The result is stored as a list in $out.result. + */}} +{{ define "srox.computeSANs" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ $svcName := index . 2 }} +{{ $releaseNS := $.Release.Namespace }} +{{ $sans := list }} +{{ range $ns := list $releaseNS "stackrox" | uniq | sortAlpha }} + {{ $baseDNS := printf "%s.%s" $svcName $ns }} + {{ range $suffix := tuple "" ".svc" ".svc.cluster.local" }} + {{ $sans = printf "%s%s" $baseDNS $suffix | append $sans }} + {{ end }} +{{ end }} +{{ $_ := set $out "result" $sans }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_defaults.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_defaults.tpl new file mode 100644 index 0000000..7f8629b --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_defaults.tpl @@ -0,0 +1,35 @@ +{{/* + srox.applyDefaults . + + Applies defaults defined in `internal/defaults`, in an order that depends on the filenames. + */}} +{{ define "srox.applyDefaults" }} +{{ $ := . }} +{{/* Apply defaults */}} +{{ range $defaultsFile, $defaultsTpl := $.Files.Glob "internal/defaults/*.yaml" }} + {{ $tplSects := regexSplit "(^|\n)---($|\n)" (toString $defaultsTpl) -1 }} + {{ $sectCounter := 0 }} + {{ range $tplSect := $tplSects }} + {{/* + tpl will merely stop creating output if an error is encountered during rendering (not during parsing), but we want + to be certain that we recognized invalid templates. Hence, add a marker line at the end, and verify that it + shows up in the output. + */}} + {{ $renderedSect := tpl (list $tplSect "{{ \"\\n#MARKER\\n\" }}" | join "") $ }} + {{ if not (hasSuffix "\n#MARKER\n" $renderedSect) }} + {{ include "srox.fail" (printf "Section %d in defaults file %s contains invalid templating" $sectCounter $defaultsFile) }} + {{ end }} + {{/* + fromYaml only returns an empty dict upon error, but we want to be certain that we recognized invalid YAML. + Hence, add a marker value. + */}} + {{ $sectDict := fromYaml (cat $renderedSect "\n__marker: true\n") }} + {{ if not (index $sectDict "__marker") }} + {{ include "srox.fail" (printf "Section %d in defaults file %s contains invalid YAML" $sectCounter $defaultsFile) }} + {{ end }} + {{ $_ := unset $sectDict "__marker" }} + {{ $_ = include "srox.mergeInto" (list $._rox $sectDict) }} + {{ $sectCounter = add $sectCounter 1 }} + {{ end }} +{{ end }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_dict.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_dict.tpl new file mode 100644 index 0000000..bf14a6d --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_dict.tpl @@ -0,0 +1,142 @@ +{{/* + srox.compactDict $target [$depth] + + Compacts a dict $target by removing entries with empty values. + By default, only the top-level dict $target itself is modified. If the optional $depth + parameter is specified and is non-zero, this determines the recursion depth over which the + compaction is applied to nested diocts as well. A $depth of -1 means to compact all nested + dicts, regardless of depth. + */}} +{{ define "srox.compactDict" }} +{{ $args := . }} +{{ if not (kindIs "slice" $args) }} + {{ $args = list $args 0 }} +{{ end }} +{{ $target := index $args 0 }} +{{ $depth := index $args 1 }} +{{ $zeroValKeys := list }} +{{ range $k, $v := $target }} + {{ if and (kindIs "map" $v) (ne $depth 0) }} + {{ include "srox.compactDict" (list $v (sub $depth 1)) }} + {{ end }} + {{ if not $v }} + {{ $zeroValKeys = append $zeroValKeys $k }} + {{ end }} +{{ end }} +{{ range $k := $zeroValKeys }} + {{ $_ := unset $target $k }} +{{ end }} +{{ end }} + +{{/* + srox.destructiveMergeOverwrite $out $dict1 $dict2... + + Recursively merges $dict1, $dict2 (in this order) into $out, similar to mergeOverwrite. + The eponymous difference is the fact that any explicit "null" entries in the source + dictionaries cause the respective entry to be deleted. + */}} +{{ define "srox.destructiveMergeOverwrite" }} +{{ $out := first . }} +{{ $toMergeList := rest . }} +{{ range $toMerge := $toMergeList }} + {{ range $k, $v := $toMerge }} + {{ if kindIs "invalid" $v }} + {{ $_ := unset $out $k }} + {{ else if kindIs "map" $v }} + {{ $outV := index $out $k }} + {{ if kindIs "invalid" $outV }} + {{ $_ := set $out $k (deepCopy $v) }} + {{ else if kindIs "map" $outV }} + {{ include "srox.destructiveMergeOverwrite" (list $outV $v) }} + {{ else }} + {{ fail (printf "when merging at key %s: incompatible kinds %s and %s" $k (kindOf $v) (kindOf $outV)) }} + {{ end }} + {{ else }} + {{ $_ := set $out $k $v }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox.stringifyDictValues $dict + + Recursively traverses $dict and converts every non-dict value to a string. + */}} +{{ define "srox.stringifyDictValues" }} +{{ $dict := . }} +{{ range $k, $v := $dict }} + {{ if kindIs "map" $v }} + {{ include "srox.stringifyDictValues" $v }} + {{ else }} + {{ $_ := set $dict $k (toString $v) }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox.safeDictLookup $dict $out $path + + Looks up $path in $dict, and stores the result (if any) in $out.result. + $path is a dot-separated list of nested field names. An empty $path causes + $dict to be stored in $out.result. + + Example: srox.safeDictLookup $dict $out "a.b.c" stores the value of $dict.a.b.c, if + it exists, in $out.result. Otherwise, it does nothing - in particular, it does + not fail, as accessing $dict.a.b.c unconditionally would if any of $dict, $dict.a, + or $dict.a.b was not a dict. + */}} +{{ define "srox.safeDictLookup" }} +{{ $dict := index . 0 }} +{{ $out := index . 1 }} +{{ $path := index . 2 }} +{{ $curr := $dict }} +{{ $pathList := splitList "." $path | compact }} +{{ range $pathElem := $pathList }} + {{ if kindIs "map" $curr }} + {{ $curr = index $curr $pathElem }} + {{ else if not (kindIs "invalid" $curr) }} + {{ $curr = dict.nil }} + {{ end }} +{{ end }} +{{ if not (kindIs "invalid" $curr) }} + {{ $_ := set $out "result" $curr }} +{{ end }} +{{ end }} + + + +{{/* + srox.mergeInto $tgt $src1..$srcN + + Recursively merges values from $src1, ..., $srcN into $tgt, giving preference to + values in $tgt. + + Unlike Sprig's merge, this does not overwrite falsy values when explicitly defined, + with the exception of `null` values (this also sets it apart from Sprig's mergeOverwrite). + + Whenever entire (nested) dicts are merged as-is from one of the sources into $tgt, a deep + copy of the respective nested dict is created. + + An empty string is always returned, hence this should be invoked in the form + $_ := include "srox.mergeInto" (list $tgt $src1 $src2) + */}} +{{ define "srox.mergeInto" }} +{{ $tgt := first . }} +{{ range $src := rest . }} + {{ range $k, $srcV := $src }} + {{ $tgtV := index $tgt $k }} + {{ if kindIs "map" $srcV }} + {{ if kindIs "invalid" $tgtV }} + {{ $_ := set $tgt $k (deepCopy $srcV) }} + {{ else if kindIs "map" $tgtV }} + {{ $_ := include "srox.mergeInto" (list $tgtV $srcV) }} + {{ else }} + {{ fail (printf "Incompatible kinds for key %s: %s vs %s" $k (kindOf $srcV) (kindOf $tgtV)) }} + {{ end }} + {{ else if and (not (kindIs "invalid" $srcV)) (kindIs "invalid" $tgtV) }} + {{ $_ := set $tgt $k $srcV }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_expand.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_expand.tpl new file mode 100644 index 0000000..ed1cb1f --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_expand.tpl @@ -0,0 +1,96 @@ +{{/* + srox.expandAll $ $target $expandable [$path] + + Expands values within $target that are flagged in $expandable, using $path + as the path from the configuration root to $target for error reporting purposes. + + If $target is nil, nothing happens. Otherwise, $target must be a dict. For every key + of $target that is also present in $expandable, the following action is performed: + - If the entry in $expandable is a dict, recursive invoke "srox.expandAll" on the + respective entries, with an adjusted $path. + - Otherwise, the entry in $expandable is assume to be of boolean value. If the value is + true, the corresponding entry's value in $target is expanded (see "srox._expandSingle" + below for a definition of expanding), and the result of the expansion is stored under + the key with a "_" prepended in $target. The original entry in $target is removed. This + ensures "srox.expandAll" is an idempotent operation). + */}} +{{ define "srox.expandAll" }} +{{ $args := . }} +{{ $ := index $args 0 }} +{{ $target := index $args 1 }} +{{ $expandable := index $args 2 }} +{{ $path := list }} +{{ if ge (len $args) 4 }} + {{ $path = index $args 3 }} + {{ if kindIs "string" $path }} + {{ $path = splitList "." $path | compact }} + {{ end }} +{{ end }} + +{{ if kindIs "map" $target }} + {{ range $k, $v := $expandable }} + {{ $childPath := append $path $k }} + {{ $targetV := index $target $k }} + {{ if kindIs "map" $v }} + {{ include "srox.expandAll" (list $ $targetV $v $childPath) }} + {{ else if $v }} + {{ if not (kindIs "invalid" $targetV) }} + {{ $expanded := include "srox._expandSingle" (list $ $targetV (join "." $childPath)) }} + {{ $_ := set $target (printf "_%s" $k) $expanded }} + {{ end }} + {{ $_ := unset $target $k }} + {{ end }} + {{ end }} +{{ else if not (kindIs "invalid" $target) }} + {{ include "srox.fail" (printf "Error expanding value at %s: expected map, got: %s" (join "." $path) (kindOf $target)) }} +{{ end }} +{{ end }} + +{{/* + srox.expand $ $spec + + Parses and expands a "specification string" in the following way: + - If $spec is a dictionary, return $spec rendered as a YAML. + - Otherwise, if $spec starts with a backslash character (`\`), return $spec minus the leading + backslash character. + - Otherwise, if $spec starts with an `@` character, strip off the first character and + treat the remainder of the string as a `|`-separated list of file names. Try to load + each referenced file, in order, via `stackrox.getFile`. The result is the first file + that could be successfully loaded. If no file could be loaded, expansion fails. + - Otherwise, return $spec as-is. + */}} +{{- define "srox._expandSingle" -}} + {{- $ := index . 0 -}} + {{- $spec := index . 1 -}} + {{- $context := index . 2 -}} + {{- $result := "" -}} + {{- if kindIs "string" $spec -}} + {{- if hasPrefix "\\" $spec -}} + {{- /* use \ as string-wide escape character */ -}} + {{- $result = trimPrefix "\\" $spec -}} + {{- else if hasPrefix "@" $spec -}} + {{- /* treat as file list (first found matches) */ -}} + {{- /* If the prefix is "@?" expansion will not fail if no files could be found, instead an empty string is returned. */ -}} + {{- $fileSpec := trimPrefix "@" $spec -}} + {{- $allowNotFound := false -}} + {{- if hasPrefix "?" $fileSpec -}} + {{- $allowNotFound = true -}} + {{- $fileSpec = trimPrefix "?" $fileSpec -}} + {{- end -}} + {{- $fileList := regexSplit "\\s*\\|\\s*" ($fileSpec | trim) -1 -}} + {{- $fileRes := dict -}} + {{- $_ := include "srox.loadFile" (list $ $fileRes $fileList) -}} + {{- if and (not $allowNotFound) (not $fileRes.found) -}} + {{- include "srox.fail" (printf "Expanding %s: file reference %q: none of the referenced files were found" $context $spec) -}} + {{- end -}} + {{- $result = default "" $fileRes.contents -}} + {{- else -}} + {{/* treat as raw string */}} + {{- $result = $spec -}} + {{- end -}} + {{- else if not (kindIs "invalid" $spec) -}} + {{- /* render non-string, non-nil values as YAML */ -}} + {{- $result = toYaml $spec -}} + {{- end -}} + {{- $result -}} +{{- end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_format.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_format.tpl new file mode 100644 index 0000000..745fe47 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_format.tpl @@ -0,0 +1,14 @@ +{{/* + srox.formatStorageSize $value + + Formats $value as a storage size. $value can be an integer or a string. + If no unit is specified (e.g., if $value is a string), a default unit of + Gigabytes ("Gi" suffix) is assumed. + */}} +{{- define "srox.formatStorageSize" -}} +{{- $val := toString . -}} +{{- if regexMatch "^[0-9]+$" $val -}} + {{- $val = printf "%sGi" $val -}} +{{- end -}} +{{- default "0" $val -}} +{{- end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_helpers.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_helpers.tpl new file mode 100644 index 0000000..e87f10f --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_helpers.tpl @@ -0,0 +1,68 @@ +{{/* + Misceallaneous helper templates. + */}} + + + + +{{/* + srox.loadFile $ $out $fileName-or-list + + This helper function reads a file. It differs from $.Files.Get in that it also takes + $._rox.meta.fileOverrides into account. Furthermore, it can receive a list of file names, + and will try these files in order. Finally, it indicates whether a file was found via the + $out.found property (as opposed to $.Files.Get, which cannot distinguish between a successful + read of an empty file, and this file not being found). + The file contents will be returned via $out.contents + */}} +{{ define "srox.loadFile" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ $fileNames := index . 2 }} +{{ if not (kindIs "slice" $fileNames) }} + {{ $fileNames = list $fileNames }} +{{ end }} +{{ $contents := index dict "" }} +{{ range $fileName := $fileNames }} + {{ if kindIs "invalid" $contents }} + {{ $contents = index $._rox.meta.fileOverrides $fileName }} + {{ end }} + {{ if kindIs "invalid" $contents }} + {{ range $path, $_ := $.Files.Glob $fileName }} + {{ if kindIs "invalid" $contents }} + {{ $contents = $.Files.Get $path }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ if not (kindIs "invalid" $contents) }} + {{ $_ := set $out "contents" $contents }} +{{ end }} +{{ $_ := set $out "found" (not (kindIs "invalid" $contents)) }} +{{ end }} + + +{{/* + srox.checkGenerated $ $cfgPath + + Checks if the value at configuration path $cfgPath (e.g., "central.adminPassword.value") was + generated. Evaluates to the string "true" if this is the case, and an empty string otherwise. + */}} +{{- define "srox.checkGenerated" -}} +{{- $ := index . 0 -}} +{{- $cfgPath := index . 1 -}} +{{- $genCfg := $._rox._state.generated -}} +{{- $exists := true -}} +{{- range $pathElem := splitList "." $cfgPath -}} + {{- if $exists -}} + {{- if hasKey $genCfg $pathElem -}} + {{- $genCfg = index $genCfg $pathElem -}} + {{- else -}} + {{- $exists = false -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $exists -}} +true +{{- end -}} +{{- end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_image-pull-secrets.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_image-pull-secrets.tpl new file mode 100644 index 0000000..9747e26 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_image-pull-secrets.tpl @@ -0,0 +1,85 @@ +{{/* + srox.configureImagePullSecrets $ $cfgName $imagePullSecrets $secretResourceName $defaultSecretNames $namespace + + Configures image pull secrets. + + This function enriches $imagePullSecrets based on the exposed configuration parameters to contain + a list of Kubernetes secret names as `_names` to be used as image pull secrets within the chart + templates. This list contains the following secrets: + + - Secrets referenced via $imagePullSecrets.useExisting. + - Image pull secrets associated with the default service account (if + $imagePullSecrets.useFromDefaultServiceAccount is true). + - $secretResourceName, if $imagePullSecrets.username is set. + - $defaultSecretNames. */}} + +{{ define "srox.configureImagePullSecrets" }} +{{ $ := index . 0 }} +{{ $cfgName := index . 1 }} +{{ $imagePullSecrets := index . 2 }} +{{ $secretResourceName := index . 3 }} +{{ $defaultSecretNames := index . 4 }} +{{ $namespace := index . 5 }} + +{{ $imagePullSecretNames := default list $imagePullSecrets.useExisting }} +{{ if not (kindIs "slice" $imagePullSecretNames) }} + {{ $imagePullSecretNames = regexSplit "\\s*[,;]\\s*" (trim $imagePullSecretNames) -1 }} +{{ end }} +{{ if $imagePullSecrets.useFromDefaultServiceAccount }} + {{ $defaultSA := dict }} + {{ include "srox.safeLookup" (list $ $defaultSA "v1" "ServiceAccount" $namespace "default") }} + {{ if $defaultSA.result }} + {{ range $ips := default list $defaultSA.result.imagePullSecrets }} + {{ if $ips.name }} + {{ $imagePullSecretNames = append $imagePullSecretNames $ips.name }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +{{ $imagePullCreds := dict }} +{{ if $imagePullSecrets._username }} + {{ $imagePullCreds = dict "username" $imagePullSecrets._username "password" $imagePullSecrets._password }} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretResourceName }} +{{ else if $imagePullSecrets._password }} + {{ $msg := printf "Username missing in %q. Whenever an image pull password is specified, a username must be specified as well" $cfgName }} + {{ include "srox.fail" $msg }} +{{ end }} +{{ if and $.Release.IsInstall (not $imagePullSecretNames) (not $imagePullSecrets.allowNone) }} + {{ $msg := printf "You have not specified any image pull secrets, and no existing image pull secrets were automatically inferred. If your registry does not need image pull credentials, explicitly set the '%s.allowNone' option to 'true'" $cfgName }} + {{ include "srox.fail" $msg }} +{{ end }} + +{{ $imagePullSecretNames = concat (append $imagePullSecretNames $secretResourceName) $defaultSecretNames | uniq | sortAlpha }} +{{ $_ := set $imagePullSecrets "_names" $imagePullSecretNames }} +{{ $_ := set $imagePullSecrets "_creds" $imagePullCreds }} + +{{ end }} + +{{ define "srox.configureImagePullSecretsForDockerRegistry" }} +{{ $ := index . 0 }} +{{ $imagePullSecrets := index . 1 }} + +{{/* Setup Image Pull Secrets for Docker Registry. + Note: This must happen afterwards, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} +{{ if $imagePullSecrets._username }} + {{ $dockerAuths := dict }} + {{ range $image := keys $._rox._state.referencedImages }} + {{ $registry := splitList "/" $image | first }} + {{ if eq $registry "docker.io" }} + {{/* Special case docker.io */}} + {{ $registry = "https://index.docker.io/v1/" }} + {{ else }} + {{ $registry = printf "https://%s" $registry }} + {{ end }} + {{ $_ := set $dockerAuths $registry dict }} + {{ end }} + {{ $authToken := printf "%s:%s" $imagePullSecrets._username $imagePullSecrets._password | b64enc }} + {{ range $regSettings := values $dockerAuths }} + {{ $_ := set $regSettings "auth" $authToken }} + {{ end }} + + {{ $_ := set $imagePullSecrets "_dockerAuths" $dockerAuths }} +{{ end }} + +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_images.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_images.tpl new file mode 100644 index 0000000..dced29d --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_images.tpl @@ -0,0 +1,34 @@ +{{/* + srox.configureImage $ $imageCfg + + Configures settings for a single image by augmenting/completing an existing image configuration + stanza. + + If $imageCfg.fullRef is empty: + First, the image registry is determined by inspecting $imageCfg.registry and, if this is empty, + $._rox.image.registry, ultimately defaulting to `docker.io`. The full image ref is then + constructed from the registry, $imageCfg.name (must be non-empty), and $imageCfg.tag (may be + empty, in which case "latest" is assumed). The result is stored in $imageCfg.fullRef. + + Afterwards (irrespective of the previous check), $imageCfg.fullRef is modified by prepending + "docker.io/" if and only if it did not contain a remote yet (i.e., the part before the first "/" + did not contain a dot (DNS name) or colon (port)). + + Finally, the resulting $imageCfg.fullRef is stored as a dict entry with value `true` in the + $._rox._state.referencedImages dict. + */}} +{{ define "srox.configureImage" }} +{{ $ := index . 0 }} +{{ $imageCfg := index . 1 }} +{{ $imageRef := $imageCfg.fullRef }} +{{ if not $imageRef }} + {{ $imageRef = printf "%s/%s:%s" (coalesce $imageCfg.registry $._rox.image.registry "docker.io") $imageCfg.name (default "latest" $imageCfg.tag) }} +{{ end }} +{{ $imageComponents := splitList "/" $imageRef }} +{{ $firstComponent := index $imageComponents 0 }} +{{ if or (lt (len $imageComponents) 2) (and (not (contains ":" $firstComponent)) (not (contains "." $firstComponent))) }} + {{ $imageRef = printf "docker.io/%s" $imageRef }} +{{ end }} +{{ $_ := set $imageCfg "fullRef" $imageRef }} +{{ $_ = set $._rox._state.referencedImages $imageRef true }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_init.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_init.tpl new file mode 100644 index 0000000..fd50428 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_init.tpl @@ -0,0 +1,257 @@ +{{/* + srox.init $ + + Initialization template for the internal data structures. + This template is designed to be included in every template file, but will only be executed + once by leveraging state sharing between templates. + */}} +{{ define "srox.init" }} + +{{ $ := . }} + +{{/* + On first(!) instantiation, set up the $._rox structure, containing everything required by + the resource template files. + */}} +{{ if not $._rox }} + +{{/* + Calculate the fingerprint of the input config. + */}} +{{ $configFP := (.Values | toJson | sha256sum) }} + +{{/* + Initial Setup + */}} + +{{ $values := deepCopy $.Values }} +{{ include "srox.applyCompatibilityTranslation" (list $ $values) }} + +{{/* + $rox / ._rox is the dictionary in which _all_ data that is modified by the init logic + is stored. + We ensure that it has the required shape, and then right after merging the user-specified + $.Values, we apply some bootstrap defaults. + */}} +{{ $rox := deepCopy $values }} + + +{{ $configShape := $.Files.Get "internal/config-shape.yaml" | fromYaml }} + +{{/* Only merge scanner config shapes if feature flag is enabled and kubectl output is disabled */}} +{{ $configShapeScanner := $.Files.Get "internal/scanner-config-shape.yaml" | fromYaml }} + {{ $_ := include "srox.mergeInto" (list $rox $configShape $configShapeScanner) }} + + +{{ $_ = set $ "_rox" $rox }} + +{{/* Set the config fingerprint as computed or overridden via values. */}} +{{ $configFP = default $configFP $._rox.meta.configFingerprintOverride }} +{{ $_ = set $._rox "_configFP" $configFP }} + +{{/* Global state (accessed from sub-templates) */}} +{{ $state := dict "notes" list "warnings" list "referencedImages" dict "generated" dict }} +{{ $_ = set $._rox "_state" $state }} + +{{/* + API Server setup. The problem with `.Capabilities.APIVersions` is that Helm does not + allow setting overrides for those when using `helm template` or `--dry-run`. Thus, + if we rely on `.Capabilities.APIVersions` directly, we lose flexibility for our chart + in these settings. Therefore, we use custom fields such that a user in principle has + the option to inject via `--set`/`-f` everything we rely upon. + */}} +{{ $apiResources := list }} +{{ if not (kindIs "invalid" $._rox.meta.apiServer.overrideAPIResources) }} + {{ $apiResources = $._rox.meta.apiServer.overrideAPIResources }} +{{ else }} + {{ range $apiResource := $.Capabilities.APIVersions }} + {{ $apiResources = append $apiResources $apiResource }} + {{ end }} +{{ end }} +{{ if $._rox.meta.apiServer.extraAPIResources }} + {{ $apiResources = concat $apiResources $._rox.meta.apiServer.extraAPIResources }} +{{ end }} +{{ $apiServerVersion := coalesce $._rox.meta.apiServer.version $.Capabilities.KubeVersion.Version }} +{{ $apiServer := dict "apiResources" $apiResources "version" $apiServerVersion }} +{{ $_ = set $._rox "_apiServer" $apiServer }} + +{{/* + Environment setup +*/}} + +{{/* Detect openshift version */}} +{{ include "srox.autoSenseOpenshiftVersion" (list $) }} + +{{/* Openshift monitoring */}} +{{ if $._rox.enableOpenShiftMonitoring }} + {{ include "srox.warn" (list . "enableOpenShiftMonitoring option was replaced with monitoring.openshift.enabled") }} + {{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" true)) }} +{{ end }} +{{/* Default `monitoring.openshift.enabled = true` unless `env.openshift != 4`. */}} +{{ if kindIs "invalid" $._rox.monitoring.openshift.enabled }} +{{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" (eq $._rox.env.openshift 4))) }} +{{ end }} +{{ if and $._rox.monitoring.openshift.enabled (ne $._rox.env.openshift 4) }} + {{ include "srox.warn" (list . "'monitoring.openshift.enabled' is set to true, but the chart is not being deployed in an OpenShift 4 cluster. Proceeding with 'monitoring.openshift.enabled=false'.") }} + {{ $_ := set $._rox "monitoring" (dict "openshift" (dict "enabled" false)) }} +{{ end }} +{{/* Detect enablePodSecurityPolicies */}} +{{ include "srox.autoSensePodSecurityPolicies" (list $) }} + +{{ include "srox.applyDefaults" $ }} + +{{/* Expand applicable config values */}} +{{ $expandables := $.Files.Get "internal/expandables.yaml" | fromYaml }} +{{ include "srox.expandAll" (list $ $rox $expandables) }} + +{{/* + General validation of effective settings. + */}} + +{{ if not $.Release.IsUpgrade }} +{{ if ne $._rox._namespace "stackrox" }} + {{ if $._rox.allowNonstandardNamespace }} + {{ include "srox.note" (list $ (printf "You have chosen to deploy to namespace '%s'." $._rox._namespace)) }} + {{ else }} + {{ include "srox.fail" (printf "You have chosen to deploy to namespace '%s', not 'stackrox'. If this was accidental, please re-run helm with the '-n stackrox' option. Otherwise, if you need to deploy into this namespace, set the 'allowNonstandardNamespace' configuration value to true." $._rox._namespace) }} + {{ end }} +{{ end }} +{{ end }} + +{{/* If a cluster name should change the confirmNewClusterName value must match clusterName. */}} +{{ if and $._rox.confirmNewClusterName (ne $._rox.confirmNewClusterName $._rox.clusterName) }} + {{ include "srox.fail" (printf "Failed to change cluster name. Values for confirmNewClusterName '%s' did not match clusterName '%s'." $._rox.confirmNewClusterName $._rox.clusterName) }} +{{ end }} + + +{{ if not $.Release.IsUpgrade }} +{{ if ne $.Release.Name $.Chart.Name }} + {{ if $._rox.allowNonstandardReleaseName }} + {{ include "srox.warn" (list $ (printf "You have chosen a release name of '%s', not '%s'. Accompanying scripts and commands in documentation might require adjustments." $.Release.Name $.Chart.Name)) }} + {{ else }} + {{ include "srox.fail" (printf "You have chosen a release name of '%s', not '%s'. We strongly recommend using the standard release name. If you must use a different name, set the 'allowNonstandardReleaseName' configuration option to true." $.Release.Name $.Chart.Name) }} + {{ end }} +{{ end }} +{{ end }} + + + + + +{{ if and (not $._rox.auditLogs.disableCollection) (ne $._rox.env.openshift 4) }} + {{ include "srox.fail" "'auditLogs.disableCollection' is set to false, but the chart is not being deployed in OpenShift 4 mode. Set 'env.openshift' to '4' in order to enable OpenShift 4 features." }} +{{ end }} + + +{{ if and $._rox.admissionControl.dynamic.enforceOnCreates (not $._rox.admissionControl.listenOnCreates) }} + {{ include "srox.warn" (list $ "Incompatible settings: 'admissionControl.dynamic.enforceOnCreates' is set to true, while `admissionControl.listenOnCreates` is set to false. For the feature to be active, enable both settings by setting them to true.") }} +{{ end }} + +{{ if and $._rox.admissionControl.dynamic.enforceOnUpdates (not $._rox.admissionControl.listenOnUpdates) }} + {{ include "srox.warn" (list $ "Incompatible settings: 'admissionControl.dynamic.enforceOnUpdates' is set to true, while `admissionControl.listenOnUpdates` is set to false. For the feature to be active, enable both settings by setting them to true.") }} +{{ end }} + +{{ if and (eq $._rox.env.openshift 3) $._rox.admissionControl.listenOnEvents }} + {{ include "srox.fail" "'admissionControl.listenOnEvents' is set to true, but the chart is being deployed in OpenShift 3.x compatibility mode, which does not work with this feature. Set 'env.openshift' to '4' in order to enable OpenShift 4.x features." }} +{{ end }} +{{/* Initial image pull secret setup. */}} +{{ include "srox.mergeInto" (list $._rox.mainImagePullSecrets $._rox.imagePullSecrets) }} +{{ include "srox.configureImagePullSecrets" (list $ "mainImagePullSecrets" $._rox.mainImagePullSecrets "secured-cluster-services-main" (list "stackrox") $._rox._namespace) }} +{{ include "srox.mergeInto" (list $._rox.collectorImagePullSecrets $._rox.imagePullSecrets) }} +{{ include "srox.configureImagePullSecrets" (list $ "collectorImagePullSecrets" $._rox.collectorImagePullSecrets "secured-cluster-services-collector" (list "stackrox" "collector-stackrox") $._rox._namespace) }} + +{{/* Additional CAs. */}} +{{ $additionalCAList := list }} +{{ if kindIs "string" $._rox.additionalCAs }} + {{ if $._rox.additionalCAs }} + {{ $additionalCAList = append $additionalCAList (dict "name" "ca.crt" "contents" $._rox.additionalCAs) }} + {{ end }} +{{ else if kindIs "slice" $._rox.additionalCAs }} + {{ range $contents := $._rox.additionalCAs }} + {{ $additionalCAList = append $additionalCAList (dict "name" "ca.crt" "contents" $contents) }} + {{ end }} +{{ else if kindIs "map" $._rox.additionalCAs }} + {{ range $name := keys $._rox.additionalCAs | sortAlpha }} + {{ $additionalCAList = append $additionalCAList (dict "name" $name "contents" (get $._rox.additionalCAs $name)) }} + {{ end }} +{{ else if not (kindIs "invalid" $._rox.additionalCAs) }} + {{ include "srox.fail" (printf "Invalid kind %s for additionalCAs" (kindOf $._rox.additionalCAs)) }} +{{ end }} +{{ range $path, $contents := .Files.Glob "secrets/additional-cas/**" }} + {{ $name := trimPrefix "secrets/additional-cas/" $path }} + {{ $additionalCAList = append $additionalCAList (dict "name" $name "contents" (toString $contents)) }} +{{ end }} +{{ $additionalCAs := dict }} +{{ range $idx, $elem := $additionalCAList }} + {{ if not (kindIs "string" $elem.contents) }} + {{ include "srox.fail" (printf "Invalid non-string contents kind %s at index %d (%q) of additionalCAs" (kindOf $elem.contents) $idx $elem.name) }} + {{ end }} + {{/* In a k8s secret, no characters other than alphanumeric, '.', '_' and '-' are allowed. Also, for the + update-ca-certificates script to work, the file names must end in '.crt'. */}} + + {{ $normalizedName := printf "%02d-%s.crt" $idx (regexReplaceAll "[^[:alnum:]._-]" $elem.name "-" | trimSuffix ".crt") }} + {{ $_ := set $additionalCAs $normalizedName $elem.contents }} +{{ end }} +{{ $_ = set $._rox "_additionalCAs" $additionalCAs }} + +{{/* + Final validation (after merging in defaults). + */}} + +{{ if and ._rox.helmManaged (not ._rox.clusterName) }} + {{ include "srox.fail" "No cluster name specified. Set 'clusterName' to the desired cluster name." }} +{{ end }} + +{{/* Image settings */}} +{{ include "srox.configureImage" (list $ ._rox.image.main) }} +{{ include "srox.configureImage" (list $ ._rox.image.collector) }} +{{ include "srox.configureImage" (list $ ._rox.image.scanner) }} + +{{ include "srox.initGlobalPrefix" (list $) }} + +{{/* ManagedBy related settings */}} +{{/* The field `helmManaged` defaults to true, therefore `managedBy` will only be changed to `MANAGER_TYPE_MANUAL` here + in case it was explicitly set `helmManaged=false`. */}} +{{- if not ._rox.helmManaged }} + {{ $_ = set $._rox "managedBy" "MANAGER_TYPE_MANUAL" }} +{{- end }} + +{{/* + Local scanner setup. + */}} + +{{/* Disable scanner always in kubectl outputs */}} + + +{{ if eq ._rox.scanner.disable false }} + {{ $centralDeployment := dict }} + {{ include "srox.safeLookup" (list $ $centralDeployment "apps/v1" "Deployment" $.Release.Namespace "central") }} + {{ if $centralDeployment.result }} + {{ include "srox.note" (list $ "Detected central running in the same namespace. Not deploying scanner from this chart and configuring sensor to use existing scanner instance, if any.") }} + {{ $_ := set $._rox.sensor.localImageScanning "enabled" "true" }} + {{ $_ := set $._rox.scanner "disable" true }} + {{ end }} +{{ end }} + +{{ if eq ._rox.scanner.disable false }} + {{ if ne ._rox.scanner.mode "slim" }} + {{ include "srox.fail" (print "Only scanner slim mode is allowed in Secured Cluster. To solve this, set to slim mode: scanner.mode=slim.") }} + {{ end }} + + {{ $_ := set $._rox.sensor.localImageScanning "enabled" "true" }} + {{ $_ := set $._rox.scanner "slimImage" ._rox.image.scanner }} + {{ $_ := set $._rox.scanner "slimDBImage" ._rox.image.scannerDb }} + {{ include "srox.scannerInit" (list $ $._rox.scanner) }} + {{ include "srox.configureImagePullSecrets" (list $ "imagePullSecrets" $._rox.imagePullSecrets "secured-cluster-services-main" (list "stackrox" "stackrox-scanner") $.Release.Namespace) }} +{{ end }} + +{{/* + Post-processing steps. + */}} + +{{ include "srox.configureImagePullSecretsForDockerRegistry" (list $ ._rox.mainImagePullSecrets) }} +{{ include "srox.configureImagePullSecretsForDockerRegistry" (list $ ._rox.collectorImagePullSecrets) }} + +{{ end }} + +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_injected-ca-bundle.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_injected-ca-bundle.tpl new file mode 100644 index 0000000..f831139 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_injected-ca-bundle.tpl @@ -0,0 +1,29 @@ +{{/* + srox.injectedCABundleVolume + + Configures ConfigMap volume to use in a deployment. + */}} +{{- define "srox.injectedCABundleVolume" -}} +{{- if eq ._rox.env.openshift 4 }} +- name: trusted-ca-volume + configMap: + name: injected-cabundle-{{ .Release.Name }} + items: + - key: ca-bundle.crt + path: tls-ca-bundle.pem + optional: true +{{ end }} +{{ end }} + +{{/* + srox.injectedCABundleVolumeMount + + Mounts the srox.injectedCABundle volume to a container. + */}} +{{- define "srox.injectedCABundleVolumeMount" -}} +{{- if eq ._rox.env.openshift 4 }} +- name: trusted-ca-volume + mountPath: /etc/pki/injected-ca-trust/ + readOnly: true +{{ end }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_labels.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_labels.tpl new file mode 100644 index 0000000..52714db --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_labels.tpl @@ -0,0 +1,31 @@ +{{/* + srox._labels $labels $ $objType $objName $forPod + + Writes all applicable [pod] labels (including default labels) for $objType/$objName + into $labels. Pod labels are written iff $forPod is true. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.labels". + */}} +{{ define "srox._labels" }} +{{ $labels := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $forPod := index . 4 }} +{{ $_ := set $labels "app.kubernetes.io/name" "stackrox" }} +{{ $_ = set $labels "app.kubernetes.io/managed-by" $.Release.Service }} +{{ $_ = set $labels "helm.sh/chart" (printf "%s-%s" $.Chart.Name ($.Chart.Version | replace "+" "_")) }} +{{ $_ = set $labels "app.kubernetes.io/instance" $.Release.Name }} +{{ $_ = set $labels "app.kubernetes.io/version" $.Chart.AppVersion }} +{{ $_ = set $labels "app.kubernetes.io/part-of" "stackrox-secured-cluster-services" }} +{{ $component := regexReplaceAll "^.*/(admission-control|collector|sensor)[^/]*\\.yaml" $.Template.Name "${1}" }} +{{ if not (contains "/" $component) }} + {{ $_ = set $labels "app.kubernetes.io/component" $component }} +{{ end }} +{{ $metadataNames := list "labels" }} +{{ if $forPod }} + {{ $metadataNames = append $metadataNames "podLabels" }} +{{ end }} +{{ include "srox._customizeMetadata" (list $ $labels $objType $objName $metadataNames) }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_lookup.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_lookup.tpl new file mode 100644 index 0000000..17f6306 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_lookup.tpl @@ -0,0 +1,40 @@ +{{/* + srox.safeLookup $ $out $apiVersion $kind $ns $name + + This function does nothing if $.meta.useLookup is false; otherwise, it will + perform a `lookup $apiVersion $kind $ns $name` operation and store the result in + $out.result. + + Additionally, if a lookup was attempted, $out.reliable will contain a bool indicating + whether the result of lookup can be relied upon. This is determined to be the case if + the default service account in the release namespace can be found. + */}} +{{ define "srox.safeLookup" }} +{{ $ := index . 0 }} +{{ $out := index . 1 }} +{{ if $._rox.meta.useLookup }} + {{ if kindIs "invalid" $._rox._state.lookupWorks }} + {{ $testOut := dict }} + {{ include "srox._doLookup" (list $ $testOut "v1" "ServiceAccount" $._rox._namespace "default") }} + {{ $_ := set $._rox._state "lookupWorks" ($testOut.result | not | not) }} + {{ end }} + {{ include "srox._doLookup" . }} + {{ $_ := set $out "reliable" $._rox._state.lookupWorks }} +{{ end }} +{{ end }} + + +{{/* + srox._doLookup $ $out $apiVersion $kind $ns $name + + Calls "lookup" with arguments $apiVersion $kind $ns $name, and stores the result + in $out.result. + + This function exists to prevent a parse error if the lookup function isn't defined. It does + so by deferring the execution of lookup to a template string instantiated via `tpl`. + */}} +{{ define "srox._doLookup" }} +{{ $ := index . 0 }} +{{ $tplArgs := dict "Template" $.Template "out" (index . 1) "apiVersion" (index . 2) "kind" (index . 3) "ns" (index . 4) "name" (index . 5) }} +{{ $_ := tpl "{{ $_ := set .out \"result\" (lookup .apiVersion .kind .ns .name) }}" $tplArgs }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_metadata.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_metadata.tpl new file mode 100644 index 0000000..3ed131f --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_metadata.tpl @@ -0,0 +1,194 @@ +{{/* + srox.labels $ $objType $objName + + Format labels for $objType/$objName as YAML. + */}} +{{- define "srox.labels" -}} +{{- $labels := dict -}} +{{- $_ := include "srox._labels" (append (prepend . $labels) false) -}} +{{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.podLabels $ $objType $objName + + Format pod labels for $objType/$objName as YAML. + */}} +{{- define "srox.podLabels" -}} +{{- $labels := dict -}} +{{- $_ := include "srox._labels" (append (prepend . $labels) true) -}} +{{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.annotations $ $objType $objName + + Format annotations for $objType/$objName as YAML. + */}} +{{- define "srox.annotations" -}} +{{- $annotations := dict -}} +{{- $_ := include "srox._annotations" (append (prepend . $annotations) false) -}} +{{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.podAnnotations $ $objType $objName + + Format pod annotations for $objType/$objName as YAML. + */}} +{{- define "srox.podAnnotations" -}} +{{- $annotations := dict -}} +{{- $_ := include "srox._annotations" (append (prepend . $annotations) true) -}} +{{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.envVars $ $objType $objName $containerName + + Format environment variables for container $containerName in + $objType/$objName as YAML. + */}} +{{- define "srox.envVars" -}} +{{- $envVars := dict -}} +{{- $_ := include "srox._envVars" (prepend . $envVars) -}} +{{- range $k := keys $envVars | sortAlpha -}} +{{- $v := index $envVars $k }} +- name: {{ quote $k }} +{{- if kindIs "map" $v }} + {{- toYaml $v | nindent 2 }} +{{- else }} + value: {{ quote $v }} +{{- end }} +{{ end -}} +{{- end -}} + +{{/* + srox._annotations $annotations $ $objType $objName $forPod + + Writes all applicable [pod] annotations (including default annotations) for + $objType/$objName into $annotations. Pod labels are written iff $forPod is true. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.annotations". + */}} +{{ define "srox._annotations" }} +{{ $annotations := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $forPod := index . 4 }} +{{ $_ := set $annotations "meta.helm.sh/release-namespace" $.Release.Namespace }} +{{ $_ = set $annotations "meta.helm.sh/release-name" $.Release.Name }} +{{ $_ = set $annotations "owner" "stackrox" }} +{{ $_ = set $annotations "email" "support@stackrox.com" }} +{{ $metadataNames := list "annotations" }} +{{ if $forPod }} + {{ $metadataNames = append $metadataNames "podAnnotations" }} +{{ end }} +{{ include "srox._customizeMetadata" (list $ $annotations $objType $objName $metadataNames) }} +{{ end }} + +{{/* + srox._envVars $envVars $ $objType $objName $containerName + + Writes all applicable environment variables for $objType/$objName + into $envVars. + + This template receives the $ parameter as its second (not its first, as usual) parameter + such that it can be used easier in "srox.envVars". + */}} +{{ define "srox._envVars" }} +{{ $envVars := index . 0 }} +{{ $ := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $containerName := index . 4 }} +{{ $metadataNames := list "envVars" }} +{{ include "srox._customizeMetadata" (list $ $envVars $objType $objName $metadataNames) }} +{{ if $containerName }} + {{ $containerKey := printf "/%s" $containerName }} + {{ $envVarsForContainer := index $envVars $containerKey }} + {{ if $envVarsForContainer }} + {{ include "srox.destructiveMergeOverwrite" (list $envVars $envVarsForContainer) }} + {{ end }} +{{ end }} + +{{/* Remove all entries starting with / */}} +{{ range $key, $_ := $envVars }} + {{ if hasPrefix "/" $key }} + {{ $_ := unset $envVars $key }} + {{ end }} +{{ end }} +{{ end }} + +{{/* + srox._customizeMetadata $ $metadata $objType $objName $metadataNames + + Writes custom key/value metadata to $metadata by consulting all sub-dicts with names in + $metadataNames under the applicable custom metadata locations (._rox.customize, + ._rox.customize.other.$objType/*, ._rox.customize.other.$objType/$objName, and + ._rox.customizer.$objName [workloads only]). Dictionaries are consulted in this order, with + values from dictionaries consulted later overwriting values from dictionaries consulted + earlier. + */}} +{{ define "srox._customizeMetadata" }} +{{ $ := index . 0 }} +{{ $metadata := index . 1 }} +{{ $objType := index . 2 }} +{{ $objName := index . 3 }} +{{ $metadataNames := index . 4 }} + +{{ $overrideDictPaths := list "" (printf "other.%s/*" $objType) (printf "other.%s/%s" $objType $objName) }} +{{ if has $objType (list "deployment" "daemonset") }} + {{ $overrideDictPaths = append $overrideDictPaths $objName }} +{{ end }} + +{{ range $dictPath := $overrideDictPaths }} + {{ $customizeDict := $._rox.customize }} + {{ if $dictPath }} + {{ $resolvedOut := dict }} + {{ include "srox.safeDictLookup" (list $._rox.customize $resolvedOut $dictPath) }} + {{ $customizeDict = $resolvedOut.result }} + {{ end }} + {{ if $customizeDict }} + {{ range $metadataName := $metadataNames }} + {{ $customMetadata := index $customizeDict $metadataName }} + {{ include "srox.destructiveMergeOverwrite" (list $metadata $customMetadata) }} + {{ end }} + {{ end }} +{{ end }} +{{ end }} + +{{/* Add namespace specific prefixes for global resources to avoid resource name clashes for multi-namespace deployments. */}} +{{- define "srox.globalResourceName" -}} +{{- $ := index . 0 -}} +{{- $name := index . 1 -}} + +{{- if eq $.Release.Namespace "stackrox" -}} + {{- /* Standard namespace, use resource name as is. */ -}} + {{- $name -}} +{{- else -}} + {{- /* Add global prefix to resource name. */ -}} + {{- printf "%s-%s" $._rox.globalPrefix (trimPrefix "stackrox-" $name) -}} +{{- end -}} +{{- end -}} + +{{/* + srox.initGlobalPrefix $ + + Initializes prefix for global resources. + */}} +{{- define "srox.initGlobalPrefix" -}} +{{- $ := index . 0 -}} +{{ if kindIs "invalid" $._rox.globalPrefix }} + {{ if eq $.Release.Namespace "stackrox" }} + {{ $_ := set $._rox "globalPrefix" "stackrox" }} + {{ else }} + {{ $_ := set $._rox "globalPrefix" (printf "stackrox-%s" (trimPrefix "stackrox-" $.Release.Namespace)) }} + {{ end }} +{{ end }} + +{{ if ne $._rox.globalPrefix "stackrox" }} + {{ include "srox.note" (list $ (printf "Global Kubernetes resources are prefixed with '%s'." $._rox.globalPrefix)) }} +{{- end -}} +{{- end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_openshift.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_openshift.tpl new file mode 100644 index 0000000..85201cb --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_openshift.tpl @@ -0,0 +1,47 @@ +{{/* + srox.autoSenseOpenshiftVersion $ + + This function detects the OpenShift version automatically based on the cluster the Helm chart is installed onto. + It writes the result to ._rox.env.openshift as an integer. + Possible results are: + - 3 (OpenShift 3) + - 4 (OpenShift 4) + - 0 (Non-Openshift cluster) + + If "true" is passed for $._rox.env.openshift the OpenShift version is detected based on the Kubernetes cluster version. + If the Kubernetes version is not available (i.e. when using Helm template) auto-sensing falls back on OpenShift 3 to be + backward compatible. + */}} + +{{ define "srox.autoSenseOpenshiftVersion" }} + +{{ $ := index . 0 }} +{{ $env := $._rox.env }} + +{{/* Infer OpenShift, if needed */}} +{{ if kindIs "invalid" $env.openshift }} + {{ $_ := set $env "openshift" (has "apps.openshift.io/v1" $._rox._apiServer.apiResources) }} +{{ end }} + +{{/* Infer openshift version */}} +{{ if and $env.openshift (kindIs "bool" $env.openshift) }} + {{/* Parse and add KubeVersion as semver from built-in resources. This is necessary to compare valid integer numbers. */}} + {{ $kubeVersion := semver $.Capabilities.KubeVersion.Version }} + + {{/* Default to OpenShift 3 if no openshift resources are available, i.e. in helm template commands */}} + {{ if not (has "apps.openshift.io/v1" $._rox._apiServer.apiResources) }} + {{ $_ := set $._rox.env "openshift" 3 }} + {{ else if gt $kubeVersion.Minor 11 }} + {{ $_ := set $env "openshift" 4 }} + {{ else }} + {{ $_ := set $env "openshift" 3 }} + {{ end }} + {{ include "srox.note" (list $ (printf "Based on API server properties, we have inferred that you are deploying into an OpenShift %d.x cluster. Set the `env.openshift` property explicitly to 3 or 4 to override the auto-sensed value." $env.openshift)) }} +{{ end }} +{{ if not (kindIs "bool" $env.openshift) }} + {{ $_ := set $env "openshift" (int $env.openshift) }} +{{ else if not $env.openshift }} + {{ $_ := set $env "openshift" 0 }} +{{ end }} + +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_psp.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_psp.tpl new file mode 100644 index 0000000..bffb2a0 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_psp.tpl @@ -0,0 +1,19 @@ +{{/* + srox.autoSensePodSecurityPolicies $ + */}} + +{{ define "srox.autoSensePodSecurityPolicies" }} + +{{ $ := index . 0 }} +{{ $system := $._rox.system }} + +{{ if kindIs "invalid" $system.enablePodSecurityPolicies }} + {{ $_ := set $system "enablePodSecurityPolicies" (has "policy/v1beta1" $._rox._apiServer.apiResources) }} + {{ if $system.enablePodSecurityPolicies }} + {{ include "srox.note" (list $ (printf "PodSecurityPolicies are enabled, since your environment supports them according to API server properties.")) }} + {{ else }} + {{ include "srox.note" (list $ (printf "PodSecurityPolicies are disabled, since your environment does not support them according to API server properties.")) }} + {{ end }} +{{ end }} + +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_reporting.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_reporting.tpl new file mode 100644 index 0000000..621e284 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_reporting.tpl @@ -0,0 +1,34 @@ +{{/* + srox.fail $message + + Print a nicely-formatted fatal error message and exit. + */}} +{{ define "srox.fail" }} +{{ printf "\n\nFATAL ERROR:\n%s" . | wrap 100 | fail }} +{{ end }} + +{{/* + srox.warn $ $message + + Add $message to the list of encountered warnings. + */}} +{{ define "srox.warn" }} +{{ $ := index . 0 }} +{{ $msg := index . 1 }} +{{ $warnings := $._rox._state.warnings }} +{{ $warnings = append $warnings $msg }} +{{ $_ := set $._rox._state "warnings" $warnings }} +{{ end }} + +{{/* + srox.note $ $message + + Add $message to the list notes that will be shown to the user after installation/upgrade. + */}} +{{ define "srox.note" }} +{{ $ := index . 0 }} +{{ $msg := index . 1 }} +{{ $notes := $._rox._state.notes }} +{{ $notes = append $notes $msg }} +{{ $_ := set $._rox._state "notes" $notes }} +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/_scanner_init.tpl b/rhacs/4.3.8/secured-cluster-services/templates/_scanner_init.tpl new file mode 100644 index 0000000..75fbe95 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/_scanner_init.tpl @@ -0,0 +1,40 @@ +{{/* + srox.scannerInit . $scannerConfig + + Initializes the scanner configuration. The scanner chart has two modes "full" and + "slim". + The "full" mode is used for stand-alone deployments, mostly along with StackRox's Central service. In this + mode, the image contains vulnerability data and the Helm chart can create its own certificates. + + The "slim" mode is used to deploy Scanner with a smaller image and does not generate TLS certificates, + typically deployed within a Secured Cluster to scan images stored in a registry only accessible to the current cluster. + The scanner chart defaults to "full" mode if no mode was provided. + + $scannerConfig contains all values which are configured by the user. The structure can be viewed in the according + config-shape. See internal/scanner-config-shape.yaml. + */}} + +{{ define "srox.scannerInit" }} + +{{ $ := index . 0 }} +{{ $scannerCfg := index . 1 }} + +{{ if or (eq $scannerCfg.mode "") (eq $scannerCfg.mode "full") }} + {{ include "srox.configureImage" (list $ $scannerCfg.image) }} + {{ include "srox.configureImage" (list $ $scannerCfg.dbImage) }} + + {{ $scannerCertSpec := dict "CN" "SCANNER_SERVICE: Scanner" "dnsBase" "scanner" }} + {{ include "srox.configureCrypto" (list $ "scanner.serviceTLS" $scannerCertSpec) }} + + {{ $scannerDBCertSpec := dict "CN" "SCANNER_DB_SERVICE: Scanner DB" "dnsBase" "scanner-db" }} + {{ include "srox.configureCrypto" (list $ "scanner.dbServiceTLS" $scannerDBCertSpec) }} +{{ else if eq $scannerCfg.mode "slim" }} + {{ include "srox.configureImage" (list $ $scannerCfg.slimImage) }} + {{ include "srox.configureImage" (list $ $scannerCfg.slimDBImage) }} +{{ else }} + {{ include "srox.fail" (printf "Unknown scanner mode %s" $scannerCfg.mode) }} +{{ end }} + +{{ include "srox.configurePassword" (list $ "scanner.dbPassword") }} + +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/additional-ca-sensor.yaml b/rhacs/4.3.8/secured-cluster-services/templates/additional-ca-sensor.yaml new file mode 100644 index 0000000..aa1801c --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/additional-ca-sensor.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} + +{{- if ._rox._additionalCAs }} +apiVersion: v1 +kind: Secret +metadata: + name: additional-ca-sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "additional-ca-sensor") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "additional-ca-sensor") | nindent 4 }} +type: Opaque +stringData: + {{- range $name, $cert := ._rox._additionalCAs }} + {{ $name | quote }}: | + {{- $cert | nindent 4 }} + {{- end }} +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-netpol.yaml b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-netpol.yaml new file mode 100644 index 0000000..1ab0341 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-netpol.yaml @@ -0,0 +1,46 @@ +{{- include "srox.init" . -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: admission-control-no-ingress + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "admission-control-no-ingress") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "admission-control-no-ingress") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: admission-control + ingress: + - ports: + - protocol: TCP + port: 8443 + policyTypes: + - Ingress + +{{- if ._rox.admissionControl.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: admission-control-monitoring + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "admission-control-monitoring") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "admission-control-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: admission-control + policyTypes: + - Ingress +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-pod-security.yaml b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-pod-security.yaml new file mode 100644 index 0000000..d4011f4 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-pod-security.yaml @@ -0,0 +1,76 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.system.enablePodSecurityPolicies }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: stackrox-admission-control + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-admission-control") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-admission-control") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'secret' + - 'downwardAPI' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox-admission-control-psp + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-admission-control-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-admission-control-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - stackrox-admission-control + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-admission-control-psp + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-admission-control-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-admission-control-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: stackrox-admission-control-psp +subjects: + - kind: ServiceAccount + name: admission-control + namespace: {{ ._rox._namespace }} +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-rbac.yaml b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-rbac.yaml new file mode 100644 index 0000000..1e4e11e --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-rbac.yaml @@ -0,0 +1,50 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: admission-control + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "admission-control") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "admission-control") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.mainImagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: watch-config + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "role" "watch-config") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "role" "watch-config") | nindent 4 }} +rules: + - apiGroups: [''] + resources: ['configmaps'] + verbs: ['get', 'list', 'watch'] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: admission-control-watch-config + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "admission-control-watch-config") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "admission-control-watch-config") | nindent 4 }} +subjects: + - kind: ServiceAccount + name: admission-control + namespace: {{ ._rox._namespace }} +roleRef: + kind: Role + name: watch-config + apiGroup: rbac.authorization.k8s.io diff --git a/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-scc.yaml b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-scc.yaml new file mode 100644 index 0000000..e6bb807 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-scc.yaml @@ -0,0 +1,46 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} + +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: stackrox-admission-control + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-admission-control") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-admission-control") | nindent 4 }} + kubernetes.io/description: stackrox-admission-control is the security constraint for the admission controller +users: + - system:serviceaccount:{{ ._rox._namespace }}:admission-control +priority: 0 +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +supplementalGroups: + type: RunAsAny +fsGroup: + type: RunAsAny +groups: [] +readOnlyRootFilesystem: true +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +allowedCapabilities: [] +defaultAddCapabilities: [] +requiredDropCapabilities: [] +volumes: + - configMap + - downwardAPI + - emptyDir + - secret + +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-secret.yaml b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-secret.yaml new file mode 100644 index 0000000..3abcb9a --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller-secret.yaml @@ -0,0 +1,30 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.createSecrets (and (kindIs "invalid" ._rox.createSecrets) (or ._rox.admissionControl.serviceTLS._cert ._rox.admissionControl.serviceTLS._key)) }} + +{{/* Admission control TLS secret isn't required, so do not fail here. */}} +{{- if and ._rox.ca._cert ._rox.admissionControl.serviceTLS._cert ._rox.admissionControl.serviceTLS._key }} + +apiVersion: v1 +kind: Secret +metadata: + name: admission-control-tls + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "admission-control-tls") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + {{- include "srox.annotations" (list . "secret" "admission-control-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox.ca._cert | nindent 4 }} + admission-control-cert.pem: | + {{- ._rox.admissionControl.serviceTLS._cert | nindent 4 }} + admission-control-key.pem: | + {{- ._rox.admissionControl.serviceTLS._key | nindent 4 }} + +{{- end }} +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/admission-controller.yaml b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller.yaml new file mode 100644 index 0000000..778076d --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/admission-controller.yaml @@ -0,0 +1,246 @@ +{{- include "srox.init" . -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: admission-control + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "deployment" "admission-control") | nindent 4 }} + app: admission-control + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "deployment" "admission-control") | nindent 4 }} +spec: + replicas: {{ ._rox.admissionControl.replicas }} + minReadySeconds: 0 + selector: + matchLabels: + app: admission-control + template: + metadata: + namespace: {{ ._rox._namespace }} + labels: + app: admission-control + {{- include "srox.podLabels" (list . "deployment" "admission-control") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8443" + {{- include "srox.podAnnotations" (list . "deployment" "admission-control") | nindent 8 }} + spec: + # Attempt to schedule these on master nodes + {{- if ._rox.admissionControl.tolerations }} + tolerations: + {{- toYaml ._rox.admissionControl.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.admissionControl.affinity | nindent 8 }} + {{- if ._rox.admissionControl._nodeSelector }} + nodeSelector: + {{- ._rox.admissionControl._nodeSelector | nindent 8 }} + {{- end}} + {{- if not ._rox.env.openshift }} + securityContext: + runAsUser: 4000 + fsGroup: 4000 + {{- end }} + serviceAccountName: admission-control + containers: + - image: {{ quote ._rox.image.main.fullRef }} + imagePullPolicy: {{ ._rox.admissionControl.imagePullPolicy }} + name: admission-control + readinessProbe: + httpGet: + scheme: HTTPS + path: /ready + port: 8443 + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 1 + ports: + - containerPort: 8443 + name: webhook + command: + - admission-control + resources: + {{- ._rox.admissionControl._resources | nindent 12 }} + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: ROX_SENSOR_ENDPOINT + value: {{ ._rox.sensor.endpoint }} + {{- include "srox.envVars" (list . "deployment" "admission-controller" "admission-controller") | nindent 10 }} + volumeMounts: + - name: config + mountPath: /run/config/stackrox.io/admission-control/config/ + readOnly: true + - name: config-store + mountPath: /var/lib/stackrox/admission-control/ + - name: ca + mountPath: /run/secrets/stackrox.io/ca/ + readOnly: true + - name: certs + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: ssl + mountPath: /etc/ssl + - name: pki + mountPath: /etc/pki/ca-trust/ + - name: additional-cas + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + {{- include "srox.injectedCABundleVolumeMount" . | nindent 12 }} + volumes: + - name: certs + secret: + secretName: admission-control-tls + optional: true + items: + - key: admission-control-cert.pem + path: cert.pem + - key: admission-control-key.pem + path: key.pem + - key: ca.pem + path: ca.pem + - name: ca + secret: + secretName: service-ca + optional: true + - name: config + configMap: + name: admission-control + optional: true + - name: config-store + emptyDir: {} + - name: ssl + emptyDir: {} + - name: pki + emptyDir: {} + - name: additional-cas + secret: + secretName: additional-ca-sensor + optional: true + {{- include "srox.injectedCABundleVolume" . | nindent 8 }} +--- + +apiVersion: v1 +kind: Service +metadata: + name: admission-control + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "service" "admission-control") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "service" "admission-control") | nindent 4 }} +spec: + ports: + - name: https + port: 443 + targetPort: webhook + protocol: TCP + selector: + app: admission-control + type: ClusterIP + sessionAffinity: None +--- +{{- if ne ._rox.env.openshift 3 }} +apiVersion: admissionregistration.k8s.io/v1 +{{- else }} +apiVersion: admissionregistration.k8s.io/v1beta1 +{{- end }} +kind: ValidatingWebhookConfiguration +metadata: + name: stackrox + labels: + {{- include "srox.labels" (list . "validatingwebhookconfiguration" "stackrox") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "validatingwebhookconfiguration" "stackrox") | nindent 4 }} +{{- if not (or ._rox.admissionControl.listenOnEvents ._rox.admissionControl.listenOnCreates ._rox.admissionControl.listenOnUpdates) }} +webhooks: [] +{{- else }} +webhooks: + {{- if or ._rox.admissionControl.listenOnCreates ._rox.admissionControl.listenOnUpdates }} + - name: policyeval.stackrox.io + {{- if ne ._rox.env.openshift 3 }} + sideEffects: NoneOnDryRun + admissionReviewVersions: [ "v1", "v1beta1" ] + timeoutSeconds: {{ add 2 ._rox.admissionControl.dynamic.timeout }} + {{- end }} + rules: + - apiGroups: + - '*' + apiVersions: + - '*' + operations: + {{- if ._rox.admissionControl.listenOnCreates }} + - CREATE + {{- end }} + {{- if ._rox.admissionControl.listenOnUpdates }} + - UPDATE + {{- end }} + resources: + - pods + - deployments + - replicasets + - replicationcontrollers + - statefulsets + - daemonsets + - cronjobs + - jobs + {{- if ._rox.env.openshift }} + - deploymentconfigs + {{- end }} + namespaceSelector: + matchExpressions: + - key: namespace.metadata.stackrox.io/name + operator: NotIn + values: + - stackrox + - kube-system + - kube-public + - istio-system + failurePolicy: Ignore + clientConfig: + caBundle: {{ required "The 'ca.cert' config option MUST be set to StackRox's Service CA certificate in order for the admission controller to be usable" ._rox.ca._cert | b64enc }} + service: + namespace: {{ ._rox._namespace }} + name: admission-control + path: /validate + {{- end}} + {{- if ._rox.admissionControl.listenOnEvents }} + - name: k8sevents.stackrox.io + {{- if ne ._rox.env.openshift 3 }} + sideEffects: NoneOnDryRun + admissionReviewVersions: [ "v1", "v1beta1" ] + timeoutSeconds: {{ add 2 ._rox.admissionControl.dynamic.timeout }} + {{- end }} + rules: + - apiGroups: + - '*' + apiVersions: + - '*' + operations: + - CONNECT + resources: + - pods + - pods/exec + - pods/portforward + failurePolicy: Ignore + clientConfig: + caBundle: {{ required "The 'ca.cert' config option MUST be set to StackRox's Service CA certificate in order for the admission controller to be usable" ._rox.ca._cert | b64enc }} + service: + namespace: {{ ._rox._namespace }} + name: admission-control + path: /events + {{- end }} +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/cluster-config.yaml b/rhacs/4.3.8/secured-cluster-services/templates/cluster-config.yaml new file mode 100644 index 0000000..20c81f6 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/cluster-config.yaml @@ -0,0 +1,14 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: Secret +metadata: + name: helm-cluster-config + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "helm-cluster-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "helm-cluster-config") | nindent 4 }} +stringData: + config.yaml: | + {{- tpl (.Files.Get "internal/cluster-config.yaml.tpl") . | nindent 4 }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/collector-netpol.yaml b/rhacs/4.3.8/secured-cluster-services/templates/collector-netpol.yaml new file mode 100644 index 0000000..3cf9214 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/collector-netpol.yaml @@ -0,0 +1,44 @@ +{{- include "srox.init" . -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: collector-no-ingress + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "collector-no-ingress") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "collector-no-ingress") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: collector + policyTypes: + - Ingress + +{{ if ._rox.collector.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: collector-monitoring + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "collector-monitoring") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "collector-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: collector + policyTypes: + - Ingress +{{ end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/collector-pod-security.yaml b/rhacs/4.3.8/secured-cluster-services/templates/collector-pod-security.yaml new file mode 100644 index 0000000..d11ef4b --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/collector-pod-security.yaml @@ -0,0 +1,72 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox-collector-psp + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-collector-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-collector-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - stackrox-collector + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-collector-psp + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-collector-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-collector-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: stackrox-collector-psp +subjects: + - kind: ServiceAccount + name: collector + namespace: {{ ._rox._namespace }} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: stackrox-collector + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-collector") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-collector") | nindent 4 }} +spec: + privileged: true + allowPrivilegeEscalation: true + allowedCapabilities: + - '*' + volumes: + - '*' + allowedHostPaths: + - pathPrefix: / + readOnly: true + hostNetwork: false + hostIPC: false + hostPID: true + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/collector-rbac.yaml b/rhacs/4.3.8/secured-cluster-services/templates/collector-rbac.yaml new file mode 100644 index 0000000..5d4ffd9 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/collector-rbac.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: collector + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "collector") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "collector") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := concat ._rox.collectorImagePullSecrets._names ._rox.mainImagePullSecrets._names | uniq }} +- name: {{ quote $secretName }} +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/collector-scc.yaml b/rhacs/4.3.8/secured-cluster-services/templates/collector-scc.yaml new file mode 100644 index 0000000..48d47dc --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/collector-scc.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} + +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: stackrox-collector + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-collector") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-collector") | nindent 4 }} + kubernetes.io/description: This SCC is based on privileged, hostaccess, and hostmount-anyuid +users: + - system:serviceaccount:{{ ._rox._namespace }}:collector +allowHostDirVolumePlugin: true +allowPrivilegedContainer: true +fsGroup: + type: RunAsAny +groups: [] +priority: 0 +readOnlyRootFilesystem: true +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +supplementalGroups: + type: RunAsAny +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: true +allowedCapabilities: [] +defaultAddCapabilities: [] +requiredDropCapabilities: [] +volumes: + - configMap + - downwardAPI + - emptyDir + - hostPath + - secret + +{{- else if eq ._rox.env.openshift 4 }} + +{{- if false }} +# "fake" document separator to aid GVK extraction heuristic +--- +{{- end }} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-privileged-scc + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-privileged-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-privileged-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - privileged + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: collector-use-scc + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "collector-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "collector-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-privileged-scc +subjects: +- kind: ServiceAccount + name: collector + namespace: {{ ._rox._namespace }} + +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/collector-secret.yaml b/rhacs/4.3.8/secured-cluster-services/templates/collector-secret.yaml new file mode 100644 index 0000000..6b07ea2 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/collector-secret.yaml @@ -0,0 +1,30 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.createSecrets (and (kindIs "invalid" ._rox.createSecrets) (or ._rox.collector.serviceTLS._cert ._rox.collector.serviceTLS._key)) }} + +{{- if not (and ._rox.ca._cert ._rox.collector.serviceTLS._cert ._rox.collector.serviceTLS._key) }} + {{ include "srox.fail" "Requested secret creation, but not all of CA certificate, collector certificate, collector private key are available. Set the 'createSecrets' config option to false if you do not want secrets to be created." }} +{{- end }} + +apiVersion: v1 +kind: Secret +metadata: + labels: + {{- include "srox.labels" (list . "secret" "collector-tls") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + {{- include "srox.annotations" (list . "secret" "collector-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" + name: collector-tls + namespace: {{ ._rox._namespace }} +type: Opaque +stringData: + ca.pem: | + {{- ._rox.ca._cert | nindent 4 }} + collector-cert.pem: | + {{- ._rox.collector.serviceTLS._cert | nindent 4 }} + collector-key.pem: | + {{- ._rox.collector.serviceTLS._key | nindent 4 }} + +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/collector.yaml b/rhacs/4.3.8/secured-cluster-services/templates/collector.yaml new file mode 100644 index 0000000..756c367 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/collector.yaml @@ -0,0 +1,218 @@ +{{- include "srox.init" . -}} + +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + {{- include "srox.labels" (list . "daemonset" "collector") | nindent 4 }} + service: collector + app: collector + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "daemonset" "collector") | nindent 4 }} + name: collector + namespace: {{ ._rox._namespace }} +spec: + selector: + matchLabels: + service: collector + template: + metadata: + namespace: {{ ._rox._namespace }} + labels: + service: collector + app: collector + {{- include "srox.podLabels" (list . "daemonset" "collector") | nindent 8 }} + annotations: + {{- include "srox.podAnnotations" (list . "daemonset" "collector") | nindent 8 }} + spec: + {{- if not ._rox.collector.disableTaintTolerations }} + tolerations: + {{- toYaml ._rox.collector.tolerations | nindent 6 }} + {{- end }} + {{- if ._rox.collector._nodeSelector }} + nodeSelector: + {{- ._rox.collector._nodeSelector | nindent 8 }} + {{- end}} + serviceAccountName: collector + containers: + {{- if ne ._rox.collector.collectionMethod "NO_COLLECTION"}} + - name: collector + image: {{ quote ._rox.image.collector.fullRef }} + imagePullPolicy: {{ ._rox.collector.imagePullPolicy }} + {{- if ._rox.collector.exposeMonitoring }} + ports: + - containerPort: 9090 + name: monitoring + {{- end }} + env: + - name: COLLECTOR_CONFIG + value: '{"tlsConfig":{"caCertPath":"/var/run/secrets/stackrox.io/certs/ca.pem","clientCertPath":"/var/run/secrets/stackrox.io/certs/cert.pem","clientKeyPath":"/var/run/secrets/stackrox.io/certs/key.pem"}}' + - name: COLLECTION_METHOD + value: {{ ._rox.collector.collectionMethod }} + - name: GRPC_SERVER + value: {{ ._rox.sensor.endpoint }} + - name: SNI_HOSTNAME + value: "sensor.stackrox.svc" + {{- include "srox.envVars" (list . "daemonset" "collector" "collector") | nindent 8 }} + resources: + {{- ._rox.collector._resources | nindent 10 }} + securityContext: + capabilities: + drop: + - NET_RAW + privileged: true + readOnlyRootFilesystem: true + volumeMounts: + - mountPath: /host/proc + name: proc-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /module + name: tmpfs-module + - mountPath: /host/etc + name: etc-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /host/usr/lib + name: usr-lib-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /host/sys + name: sys-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /host/dev + name: dev-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /run/secrets/stackrox.io/certs/ + name: certs + readOnly: true + {{- end }} + - command: + - stackrox/compliance + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: ROX_CALL_NODE_INVENTORY_ENABLED + value: {{ if eq ._rox.env.openshift 4 }}"true"{{ else }}"false"{{ end }} + - name: ROX_METRICS_PORT + {{- if ._rox.collector.exposeMonitoring }} + value: ":9091" + {{- else}} + value: "disabled" + {{- end }} + - name: ROX_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: ROX_ADVERTISED_ENDPOINT + value: {{ quote ._rox.sensor.endpoint }} + - name: ROX_NODE_SCANNING_ENDPOINT + value: {{ quote ._rox.collector.nodescanningEndpoint }} + {{- include "srox.envVars" (list . "daemonset" "collector" "compliance") | nindent 8 }} + image: {{ quote ._rox.image.main.fullRef }} + imagePullPolicy: {{ ._rox.collector.complianceImagePullPolicy }} + name: compliance + {{- if ._rox.collector.exposeMonitoring }} + ports: + - containerPort: 9091 + name: monitoring + {{- end }} + resources: + {{- ._rox.collector._complianceResources | nindent 10 }} + securityContext: + runAsUser: 0 + readOnlyRootFilesystem: true + {{ if not ._rox.collector.disableSELinuxOptions }} + seLinuxOptions: + type: {{ ._rox.collector.seLinuxOptionsType | default "container_runtime_t" | quote }} + {{ end }} + volumeMounts: + - mountPath: /etc/ssl/ + name: etc-ssl + - mountPath: /etc/pki/ca-trust/ + name: etc-pki-volume + - mountPath: /host + name: host-root-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /run/secrets/stackrox.io/certs/ + name: certs + readOnly: true + {{- if eq ._rox.env.openshift 4 }} + - name: node-inventory + image: {{ quote ._rox.image.scanner.fullRef }} + imagePullPolicy: IfNotPresent + command: ["/scanner", "--nodeinventory", "--config=", ""] + ports: + - containerPort: 8444 + name: grpc + resources: + {{- ._rox.collector._nodeScanningResources | nindent 10 }} + env: + - name: ROX_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + {{- include "srox.envVars" (list . "daemonset" "collector" "node-inventory") | nindent 8 }} + volumeMounts: + - mountPath: /host + name: host-root-ro + readOnly: true + mountPropagation: HostToContainer + - mountPath: /tmp/ + name: tmp-volume + - mountPath: /cache + name: cache-volume + {{- end }} + volumes: + - hostPath: + path: /proc + name: proc-ro + - emptyDir: + medium: Memory + name: tmpfs-module + - hostPath: + path: /etc + name: etc-ro + - hostPath: + path: /usr/lib + name: usr-lib-ro + - hostPath: + path: /sys/ + name: sys-ro + - hostPath: + path: /dev + name: dev-ro + - name: certs + secret: + secretName: collector-tls + items: + - key: collector-cert.pem + path: cert.pem + - key: collector-key.pem + path: key.pem + - key: ca.pem + path: ca.pem + - hostPath: + path: / + name: host-root-ro + - name: etc-ssl + emptyDir: {} + - name: etc-pki-volume + emptyDir: {} + - name: tmp-volume + emptyDir: {} + - name: cache-volume + emptyDir: + sizeLimit: 200Mi diff --git a/rhacs/4.3.8/secured-cluster-services/templates/openshift-monitoring.yaml b/rhacs/4.3.8/secured-cluster-services/templates/openshift-monitoring.yaml new file mode 100644 index 0000000..5b0aa89 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/openshift-monitoring.yaml @@ -0,0 +1,121 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.monitoring.openshift.enabled -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: secured-cluster-prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "secured-cluster-prometheus-k8s") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "role" "secured-cluster-prometheus-k8s") | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: secured-cluster-prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "secured-cluster-prometheus-k8s") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "secured-cluster-prometheus-k8s") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: secured-cluster-prometheus-k8s +subjects: +- kind: ServiceAccount + name: prometheus-k8s + namespace: openshift-monitoring + +--- + +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: "sensor-monitor-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "servicemonitor" (print "sensor-monitor-" .Release.Namespace)) | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "servicemonitor" (print "sensor-monitor-" .Release.Namespace)) | nindent 4 }} +spec: + endpoints: + - interval: 30s + path: metrics + port: monitoring-tls + scheme: https + tlsConfig: + caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt + certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt + keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key + serverName: "sensor.{{ .Release.Namespace }}.svc" + selector: + matchLabels: + app.kubernetes.io/component: sensor + namespaceSelector: + matchNames: + - "{{ .Release.Namespace }}" + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "rhacs-sensor-auth-reader-{{ .Release.Namespace }}" + namespace: kube-system + labels: + {{- include "srox.labels" (list . "rolebinding" (print "rhacs-sensor-auth-reader-" .Release.Namespace)) | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" (print "rhacs-sensor-auth-reader-" .Release.Namespace)) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: sensor + namespace: "{{ .Release.Namespace }}" + +--- + +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: "sensor-telemeter-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "prometheusrule" (print "sensor-telemeter-" .Release.Namespace )) | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "prometheusrule" (print "sensor-telemeter-" .Release.Namespace )) | nindent 4 }} +spec: + groups: + - name: rhacs.telemeter + rules: + - expr: | + max by (build, central_id, hosting, install_method, sensor_id, sensor_version) ( + rox_sensor_info{branding="RHACS"} + ) + record: rhacs:telemetry:rox_sensor_info + +{{- end -}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/sensor-netpol.yaml b/rhacs/4.3.8/secured-cluster-services/templates/sensor-netpol.yaml new file mode 100644 index 0000000..50d0d6e --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/sensor-netpol.yaml @@ -0,0 +1,88 @@ +{{- include "srox.init" . -}} + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "sensor") | nindent 4 }} +spec: + ingress: + - from: + - podSelector: + matchLabels: + app: collector + - podSelector: + matchLabels: + service: collector + - podSelector: + matchLabels: + app: admission-control +{{ if ._rox.sensor.localImageScanning.enabled }} + - podSelector: + matchLabels: + app: scanner +{{ end }} + ports: + - port: 8443 + protocol: TCP + - ports: + - port: 9443 + protocol: TCP + podSelector: + matchLabels: + app: sensor + policyTypes: + - Ingress + +{{ if ._rox.sensor.exposeMonitoring }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: sensor-monitoring + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "sensor-monitoring") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "sensor-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9090 + protocol: TCP + podSelector: + matchLabels: + app: sensor + policyTypes: + - Ingress +{{ end }} + +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: sensor-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "sensor-monitoring-tls") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "sensor-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: sensor + policyTypes: + - Ingress +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/sensor-pod-security.yaml b/rhacs/4.3.8/secured-cluster-services/templates/sensor-pod-security.yaml new file mode 100644 index 0000000..e44a807 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/sensor-pod-security.yaml @@ -0,0 +1,82 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox-sensor-psp + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-sensor-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-sensor-psp") | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - stackrox-sensor + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-sensor-psp + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-sensor-psp") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-sensor-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: stackrox-sensor-psp +subjects: + - kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} + - kind: ServiceAccount + name: sensor-upgrader + namespace: {{ ._rox._namespace }} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: stackrox-sensor + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-sensor") | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + - 'hostPath' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 4000 + max: 4000 +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/sensor-rbac.yaml b/rhacs/4.3.8/secured-cluster-services/templates/sensor-rbac.yaml new file mode 100644 index 0000000..fb061be --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/sensor-rbac.yaml @@ -0,0 +1,293 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "sensor") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.mainImagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} + +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:view-cluster + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:view-cluster") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:view-cluster") | nindent 4 }} +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - get + - watch + - list +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:monitor-cluster + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:monitor-cluster") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:monitor-cluster") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:view-cluster + apiGroup: rbac.authorization.k8s.io +--- +# Role edit has all verbs but 'use' to disallow using any SCCs (resources: *). +# The permission to 'use' SCCs should be defined at finer granularity in other roles. +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: edit + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "role" "edit") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "role" "edit") | nindent 4 }} +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - create + - get + - list + - watch + - update + - patch + - delete + - deletecollection +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: manage-namespace + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "manage-namespace") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "rolebinding" "manage-namespace") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: Role + name: edit + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:edit-workloads + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:edit-workloads") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:edit-workloads") | nindent 4 }} +rules: +- resources: + - cronjobs + - jobs + - daemonsets + - deployments + - deployments/scale + - deploymentconfigs + - pods + - replicasets + - replicationcontrollers + - services + - statefulsets + apiGroups: + - '*' + verbs: + - update + - patch + - delete +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:enforce-policies + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:enforce-policies") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:enforce-policies") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:edit-workloads + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:network-policies + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:network-policies") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:network-policies") | nindent 4 }} +rules: +- resources: + - 'networkpolicies' + apiGroups: + - networking.k8s.io + - extensions + verbs: + - get + - watch + - list + - create + - update + - patch + - delete +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:network-policies-binding + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:network-policies-binding") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:network-policies-binding") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:network-policies + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:update-namespaces + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:update-namespaces") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:update-namespaces") | nindent 4 }} +rules: +- resources: + - namespaces + apiGroups: [""] + verbs: + - update +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:update-namespaces-binding + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:update-namespaces-binding") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:update-namespaces-binding") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:update-namespaces + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:create-events + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:create-events") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:create-events") | nindent 4 }} +rules: +- resources: + - events + apiGroups: [""] + verbs: + - create + - patch + - list +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:create-events-binding + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:create-events-binding") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:create-events-binding") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:create-events + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:review-tokens + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:review-tokens") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:review-tokens") | nindent 4 }} +rules: +- resources: + - tokenreviews + apiGroups: ["authentication.k8s.io"] + verbs: + - create +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:review-tokens-binding + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:review-tokens-binding") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:review-tokens-binding") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: stackrox:review-tokens + apiGroup: rbac.authorization.k8s.io diff --git a/rhacs/4.3.8/secured-cluster-services/templates/sensor-scc.yaml b/rhacs/4.3.8/secured-cluster-services/templates/sensor-scc.yaml new file mode 100644 index 0000000..b24a8fc --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/sensor-scc.yaml @@ -0,0 +1,47 @@ +{{- include "srox.init" . -}} + +{{- if and ._rox.env.openshift ._rox.system.createSCCs }} + +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: stackrox-sensor + labels: + {{- include "srox.labels" (list . "securitycontextconstraints" "stackrox-sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "securitycontextconstraints" "stackrox-sensor") | nindent 4 }} + kubernetes.io/description: stackrox-sensor is the security constraint for the sensor +users: + - system:serviceaccount:{{ ._rox._namespace }}:sensor + - system:serviceaccount:{{ ._rox._namespace }}:sensor-upgrader +priority: 0 +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: + - '*' +supplementalGroups: + type: RunAsAny +fsGroup: + type: RunAsAny +groups: [] +readOnlyRootFilesystem: true +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: true +allowPrivilegedContainer: false +allowedCapabilities: [] +defaultAddCapabilities: [] +requiredDropCapabilities: [] +volumes: + - configMap + - downwardAPI + - emptyDir + - secret + +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/sensor-secret.yaml b/rhacs/4.3.8/secured-cluster-services/templates/sensor-secret.yaml new file mode 100644 index 0000000..848e1f2 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/sensor-secret.yaml @@ -0,0 +1,30 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.createSecrets (and (kindIs "invalid" ._rox.createSecrets) (or ._rox.sensor.serviceTLS._cert ._rox.sensor.serviceTLS._key)) }} + +{{- if not (and ._rox.ca._cert ._rox.sensor.serviceTLS._cert ._rox.sensor.serviceTLS._key) }} + {{ include "srox.fail" "Requested secret creation, but not all of CA certificate, sensor certificate, sensor private key are available. Set the 'createSecrets' config option to false if you do not want secrets to be created." }} +{{- end }} + +apiVersion: v1 +kind: Secret +metadata: + name: sensor-tls + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "sensor-tls") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + {{- include "srox.annotations" (list . "secret" "sensor-tls") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" +type: Opaque +stringData: + ca.pem: | + {{- ._rox.ca._cert | nindent 4 }} + sensor-cert.pem: | + {{- ._rox.sensor.serviceTLS._cert | nindent 4 }} + sensor-key.pem: | + {{- ._rox.sensor.serviceTLS._key | nindent 4 }} + +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/sensor.yaml b/rhacs/4.3.8/secured-cluster-services/templates/sensor.yaml new file mode 100644 index 0000000..2534f42 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/sensor.yaml @@ -0,0 +1,280 @@ +{{- include "srox.init" . -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "deployment" "sensor") | nindent 4 }} + app: sensor + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "deployment" "sensor") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: sensor + strategy: + type: Recreate + template: + metadata: + labels: + app: sensor + {{- include "srox.podLabels" (list . "deployment" "sensor") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "8443,9443" + {{- include "srox.podAnnotations" (list . "deployment" "sensor") | nindent 8 }} + spec: + {{- if ._rox.sensor._nodeSelector }} + nodeSelector: + {{- ._rox.sensor._nodeSelector | nindent 8 }} + {{- end}} + {{- if ._rox.sensor.tolerations }} + tolerations: + {{- toYaml ._rox.sensor.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.sensor.affinity | nindent 8 }} + {{- if not ._rox.env.openshift }} + securityContext: + runAsUser: 4000 + fsGroup: 4000 + {{- end }} + serviceAccountName: sensor + containers: + - image: {{ quote ._rox.image.main.fullRef }} + imagePullPolicy: {{ ._rox.sensor.imagePullPolicy }} + name: sensor + readinessProbe: + httpGet: + scheme: HTTPS + path: /ready + port: 9443 + ports: + - containerPort: 8443 + name: api + - containerPort: 9443 + name: webhook + {{- if ._rox.sensor.exposeMonitoring }} + - containerPort: 9090 + name: monitoring + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - containerPort: 9091 + name: monitoring-tls + {{- end }} + command: + - kubernetes-sensor + resources: + {{- ._rox.sensor._resources | nindent 10 }} + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + env: + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ROX_CENTRAL_ENDPOINT + value: {{ ._rox.centralEndpoint }} + - name: ROX_ADVERTISED_ENDPOINT + value: {{ ._rox.sensor.endpoint }} + {{- if ._rox.env.openshift }} + - name: ROX_OPENSHIFT_API + value: "true" + {{- end }} + {{- if ._rox.sensor.localImageScanning.enabled }} + - name: ROX_SCANNER_GRPC_ENDPOINT + value: {{ printf "scanner.%s.svc:8443" .Release.Namespace }} + - name: ROX_LOCAL_IMAGE_SCANNING_ENABLED + value: "true" + {{- end }} + - name: ROX_HELM_CLUSTER_CONFIG_FP + value: {{ quote ._rox._configFP }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + {{- end }} + {{- include "srox.envVars" (list . "deployment" "sensor" "sensor") | nindent 8 }} + volumeMounts: + - name: varlog + mountPath: /var/log/stackrox/ + - name: sensor-etc-ssl-volume + mountPath: /etc/ssl/ + - name: sensor-etc-pki-volume + mountPath: /etc/pki/ca-trust/ + - name: certs + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: cache + mountPath: /var/cache/stackrox + - name: helm-cluster-config + mountPath: /run/secrets/stackrox.io/helm-cluster-config/ + readOnly: true + - name: helm-effective-cluster-name + mountPath: /run/secrets/stackrox.io/helm-effective-cluster-name/ + readOnly: true + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + volumes: + - name: certs + secret: + secretName: sensor-tls + items: + - key: sensor-cert.pem + path: cert.pem + - key: sensor-key.pem + path: key.pem + - key: ca.pem + path: ca.pem + - name: sensor-etc-ssl-volume + emptyDir: {} + - name: sensor-etc-pki-volume + emptyDir: {} + - name: additional-ca-volume + secret: + secretName: additional-ca-sensor + optional: true + - name: varlog + emptyDir: {} + - name: cache + emptyDir: {} + - name: helm-cluster-config + secret: + secretName: helm-cluster-config + optional: true + - name: helm-effective-cluster-name + secret: + secretName: helm-effective-cluster-name + optional: true + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: sensor-monitoring-tls + optional: true + {{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + name: sensor + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "service" "sensor") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "service" "sensor") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: sensor-monitoring-tls + {{- end }} +spec: + ports: + - name: https + port: 443 + targetPort: api + protocol: TCP + {{- if ._rox.sensor.exposeMonitoring }} + - name: monitoring + port: 9090 + targetPort: monitoring + protocol: TCP + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + port: 9091 + targetPort: monitoring-tls + protocol: TCP + {{- end }} + selector: + app: sensor + type: ClusterIP + sessionAffinity: None +--- + +{{- if ._rox.env.istio }} +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: sensor-internal-no-istio-mtls + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "sensor-internal-no-istio-mtls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "destinationrule" "sensor-internal-no-istio-mtls") | nindent 4 }} + stackrox.io/description: "Disable Istio mTLS for port 443, since StackRox services use built-in mTLS." +spec: + host: sensor.stackrox.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 443 + tls: + mode: DISABLE +--- +{{- end }} + +apiVersion: v1 +kind: Service +metadata: + name: sensor-webhook + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "service" "sensor-webhook") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "service" "sensor-webhook") | nindent 4 }} +spec: + ports: + - name: https + port: 443 + targetPort: webhook + protocol: TCP + selector: + app: sensor + type: ClusterIP + sessionAffinity: None +{{- if or .Release.IsInstall (eq ._rox.confirmNewClusterName ._rox.clusterName) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: helm-effective-cluster-name + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "helm-effective-cluster-name") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": "keep" + {{- include "srox.annotations" (list . "secret" "helm-effective-cluster-name") | nindent 4 }} +stringData: + cluster-name: | + {{- ._rox.clusterName | nindent 4 }} +{{- end}} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/service-ca.yaml b/rhacs/4.3.8/secured-cluster-services/templates/service-ca.yaml new file mode 100644 index 0000000..3f3b5fd --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/service-ca.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} + +apiVersion: v1 +kind: Secret +metadata: + name: service-ca + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "secret" "service-ca") | nindent 4 }} + auto-upgrade.stackrox.io/component: sensor + annotations: + {{- include "srox.annotations" (list . "secret" "service-ca") | nindent 4 }} +type: Opaque +stringData: + ca.pem: | + {{- required "A CA certificate must be specified" ._rox.ca._cert | nindent 4 }} diff --git a/rhacs/4.3.8/secured-cluster-services/templates/upgrader-serviceaccount.yaml b/rhacs/4.3.8/secured-cluster-services/templates/upgrader-serviceaccount.yaml new file mode 100644 index 0000000..af12eb1 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/templates/upgrader-serviceaccount.yaml @@ -0,0 +1,36 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.createUpgraderServiceAccount }} + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sensor-upgrader + namespace: {{ ._rox._namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "sensor-upgrader") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "sensor-upgrader") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.mainImagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: stackrox:upgrade-sensors + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:upgrade-sensors") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:upgrade-sensors") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor-upgrader + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io + +{{- end }} diff --git a/rhacs/4.3.8/secured-cluster-services/values-private.yaml.example b/rhacs/4.3.8/secured-cluster-services/values-private.yaml.example new file mode 100644 index 0000000..ecdec21 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/values-private.yaml.example @@ -0,0 +1,19 @@ +# # BEGIN CONFIGURATION VALUES SECTION +# +# # Image pull credentials. If you do not specify these, you need to specify one of +# # the following: +# # - `imagePullSecrets.allowNone=true`: in case your registry allows pulling images without +# # credentials. +# # - `imagePullSecrets.useExisting="secret1;secret2;..."`: in case you have pre-existing image +# # pull secrets with the given name already created in the target namespace. +# # - `imagePullSecrets.useFromDefaultServiceAccount=true`: in case the default service account +# # in the target namespace is configured with sufficiently scoped image pull secrets. +# # +# # Since the above settings do not expose any confidential data, they can safely be added +# # to the values-public.yaml configuration file or provided on the command line. +# +# # If you do not know if any of the above applies to your situation, your best course of +# # action is probably to enter your image pull credentials here. +# imagePullSecrets: +# username: +# password: diff --git a/rhacs/4.3.8/secured-cluster-services/values-public.yaml.example b/rhacs/4.3.8/secured-cluster-services/values-public.yaml.example new file mode 100644 index 0000000..5bb9dc4 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/values-public.yaml.example @@ -0,0 +1,465 @@ +# StackRox Kubernetes Security Platform - Secured Cluster Services Chart +# PUBLIC configuration file. +# +# This file contains general configuration values relevant for the deployment of the +# StackRox Kubernetes Platform Secured Cluster Services components, which do not contain +# or reference sensitive data. This file can and should be stored in a source code +# management system and should be referenced on each `helm upgrade`. +# +# Most of the values in this file are optional, and you only should need to make modifications +# if the default deployment configuration is not sufficient for you for whatever reason. +# The most notable exceptios are +# +# - `clusterName`, +# - `centralEndpoint` and +# - `imagePullSecrets`. +# +# # BEGIN CONFIGURATION VALUES SECTION +# +## The cluster name. A new cluster of this name will be automatically registered at StackRox Central +## when deploying this Helm chart. Make sure that this name is unique among the set of secured clusters. +#clusterName: null +# +## To change the cluster name, confirm the new cluster name in this field. It should match the `clusterName` value. +## You don't need to change this unless you upgrade and change the value for clusterName. +## In this case, set it to the new value of clusterName. This option exists to prevent you from accidentally +## creating a new cluster with a different name. +#confirmNewClusterName: null +# +## Custom labels associated with a secured cluster in StackRox. +#clusterLabels: {} +# +## The gRPC endpoint for accessing StackRox Central. +#centralEndpoint: central.{{ .Release.Namespace }}.svc:443 +# +## A dictionary of additional CA certificates to include (PEM encoded). +## For example: +## additionalCAs: +## acme-labs-ca.pem: | +## -----BEGIN CERTIFICATE----- +## [...] +## -----END CERTIFICATE----- +#additionalCAs: null +# +# Specify `true` to create the `sensor-upgrader` account. By default, the StackRox Kubernetes +# Security Platform creates a service account called `sensor-upgrader` in each secured cluster. +# This account is highly privileged but is only used during upgrades. If you don’t create this +# account, you will have to complete future upgrades manually if the Sensor doesn’t have enough +# permissions. See +# [Enable automatic upgrades for secured clusters](https://help.stackrox.com/docs/configure-stackrox/enable-automatic-upgrades/) +# for more information. +# Note that auto-upgrades for Helm-managed clusters are disabled. +#createUpgraderServiceAccount: false +# +## Configuration for image pull secrets. +## These should usually be set via the command line when running `helm install`, e.g., +## helm install --set imagePullSecrets.username=myuser --set imagePullSecrets.password=mypass, +## or be stored in a separate YAML-encoded secrets file. +#imagePullSecrets: +# +# # If no image pull secrets are provided, an installation would usually fail. In order to +# # prevent it from failing, this option must explicitly be set to true. +# allowNone: false +# +# # If there exist available image pull secrets in the cluster that are managed separately, +# # set this value to the list of the respective secret names. While it is recommended to +# # record the secret names in a persisted YAML file, providing a single string containing +# # a comma-delimited list of secret names is also supported, for easier interaction with +# # --set. +# useExisting: [] +# +# # Whether to import any secrets from the default service account existing in the StackRox +# # namespace. The default service account often contains "standard" image pull secrets that +# # should be used by default for image pulls, hence this defaults to true. Only has an effect +# # if server-side lookups are enabled. +# useFromDefaultServiceAccount: true +# +## Settings regarding the installation environment +#env: +# # Treat the environment as an OpenShift cluster. Leave this unset to use auto-detection +# # based on available API resources on the server. +# # Set it to true to auto-detect the OpenShift version, otherwise set it explicitly. +# # Possible values: null, false, true, 3, 4 +# openshift: null +# +# # Treat the environment as Istio-enabled. Leave this unset to use auto-detection based on +# # available API resources on the server. +# # Possible values: null, false, true +# istio: null +# +## PEM-encoded StackRox Service CA certificate. +#ca: +# cert: null +# +## Image configuration +#image: +# # The image registry to use. Unless overridden in the more specific configs, this +# # determines the base registry for each image referenced in this config file. +# registry: my.image-registry.io +# +# # Configuration for the `main` image -- used by Sensor, Admission Control, Compliance. +# main: +# registry: null # if set to null, use `image.registry` +# name: main # the final image name is composed of the registry and the name, plus the tag below +# tag: null # should be left as null - will get picked up from the Chart version. +# fullRef: null # you can set a full image reference such as stackrox.io/main:1.2.3.4 here, but this is not +# # recommended. +# # The default pull policy for this image. Can be overridden for each individual service. +# pullPolicy: IfNotPresent +# +# # Configuration for the `collector` image -- used by Collector. +# collector: +# registry: null +# name: collector +# tag: null +# fullRef: null +# pullPolicy: IfNotPresent +# +## Sensor specific configuration. +#sensor: +# +# # Kubernetes image pull policy for Sensor. +# imagePullPolicy: IfNotPresent +# +# # Resource configuration for the sensor container. +# resources: +# requests: +# memory: "4Gi" +# cpu: "2" +# limits: +# memory: "8Gi" +# cpu: "4" +# +# # Settings for the internal service-to-service TLS certificate used by Sensor. +# serviceTLS: +# cert: null +# key: null +# +# # Use a nodeSelector for sensor +# nodeSelector +# environment: production +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # Sensor is single-homed, so avoid preemptible nodes. +# - weight: 100 +# preference: +# matchExpressions: +# - key: cloud.google.com/gke-preemptible +# operator: NotIn +# values: +# - "true" +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/infra +# operator: Exists +# - weight: 25 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/compute +# operator: Exists +# # From v1.20 node-role.kubernetes.io/control-plane replaces node-role.kubernetes.io/master (removed in +# # v1.25). We apply both because our goal is not to run pods on control plane nodes for any version of k8s. +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/master +# operator: DoesNotExist +# - weight: 100 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/control-plane +# operator: DoesNotExist +# +# # Address of the Sensor endpoint including port number. No trailing slash. +# # Rarely needs to be changed. +# endpoint: sensor.stackrox.svc:443 +# +## Admission Control specific configuration. +#admissionControl: +# +# # This setting controls whether the cluster is configured to contact the StackRox +# # Kubernetes Security Platform with `AdmissionReview` requests for create events on +# # Kubernetes objects. +# listenOnCreates: false +# +# # This setting controls whether the cluster is configured to contact the StackRox Kubernetes +# # Security Platform with `AdmissionReview` requests for update events on Kubernetes objects. +# listenOnUpdates: false +# +# # This setting controls whether the cluster is configured to contact the StackRox +# # Kubernetes Security Platform with `AdmissionReview` requests for update Kubernetes events +# # like exec and portforward. +# # +# # Defaults to `false` on OpenShift, to `true` otherwise. +# listenOnEvents: true +# +# # Use a nodeSelector for admission control pods +# nodeSelector +# environment: production +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # node-role.kubernetes.io/master is replaced by node-role.kubernetes.io/control-plane from certain version +# # of k8s. We apply both to be compatible with any k8s version. +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/master +# operator: Exists +# - weight: 50 +# preference: +# matchExpressions: +# - key: node-role.kubernetes.io/control-plane +# operator: Exists +# podAntiAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 60 +# podAffinityTerm: +# topologyKey: "kubernetes.io/hostname" +# labelSelector: +# matchLabels: +# app: admission-control +# +# # Dynamic part of the configuration which is retrieved from Central and can be modified through +# # the frontend. +# dynamic: +# +# # It controls whether the StackRox Kubernetes Security Platform evaluates policies for object +# # updates; if it’s disabled, all `AdmissionReview` requests are automatically accepted. You must +# # specify `listenOnUpdates` as `true` for this to work. +# enforceOnUpdates: false +# +# # Controls whether the StackRox Kubernetes Security Platform evaluates policies. +# # If disabled, all AdmissionReview requests are automatically accepted. You must specify +# # `listenOnCreates` as `true` for this to work. +# enforceOnCreates: false +# +# scanInline: false +# +# # If enabled, bypassing the Admission Controller is disabled. +# disableBypass: false +# +# # The maximum time in seconds, the StackRox Kubernetes Security Platform should wait while +# # evaluating admission review requests. Use it to set request timeouts when you enable image scanning. +# # If the image scan runs longer than the specified time, the StackRox Kubernetes Security Platform +# # accepts the request. Other enforcement options, such as scaling the deployment to zero replicas, +# # are still applied later if the image violates applicable policies. +# timeout: 3 +# +# # Kubernetes image pull policy for Admission Control. +# imagePullPolicy: IfNotPresent +# +# # Resource configuration for the Admission Control container. +# resources: +# requests: +# memory: "100Mi" +# cpu: "50m" +# limits: +# memory: "500Mi" +# cpu: "500m" +# +# # Replicas configures the replicas of the admission controller pod. +# replicas: 3 +# +# # Settings for the internal service-to-service TLS certificate used by Admission Control. +# serviceTLS: +# cert: null +# key: null +# +## Collector specific configuration. +#collector: +# +# # Collection method to use. Can be one of: +# # - EBPF +# # - CORE_BPF +# # - NO_COLLECTION +# collectionMethod: EBPF +# +# # Configure usage of taint tolerations. If `false`, tolerations are applied to collector, +# # and the collector pods can schedule onto all nodes with taints. If `true`, no tolerations +# # are applied, and the collector pods won't scheduled onto nodes with taints. +# disableTaintTolerations: false +# +# # Configure whether slim Collector images should be used or not. Using slim Collector images +# # requires Central to provide the matching kernel module or eBPF probe. If you are running +# # the StackRox Kubernetes Security Platform in offline mode, you must download a kernel support +# # package from [stackrox.io](https://install.stackrox.io/collector/support-packages/index.html) +# # and upload it to Central for slim Collectors to function. Otherwise, you must ensure that +# # Central can access the online probe repository hosted at https://collector-modules.stackrox.io/. +# slimMode: false +# +# # Kubernetes image pull policy for Collector. +# imagePullPolicy: IfNotPresent +# +# # Resource configuration for the Collector container. +# resources: +# requests: +# memory: "320Mi" +# cpu: "50m" +# limits: +# memory: "1Gi" +# cpu: "750m" +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - operator: "Exists" +# +# complianceImagePullPolicy: IfNotPresent +# +# # Resource configuration for the Compliance container. +# complianceResources: +# requests: +# memory: "10Mi" +# cpu: "10m" +# limits: +# memory: "2Gi" +# cpu: "1" +# +# # Resource configuration for the Node Inventory container. +# nodeScanningResources: +# requests: +# memory: "10Mi" +# cpu: "10m" +# limits: +# memory: "500Mi" +# cpu: "1" +# +# # Settings for the internal service-to-service TLS certificate used by Collector. +# serviceTLS: +# cert: null +# key: null +# +# # Settings configuring the ingestion of audit logs: +# auditLogs: +# # Disable audit log collection. This setting defaults to false on OpenShift 4 clusters. On all other cluster types, +# # it defaults to true, and setting it to false will result in an error. +# disableCollection: false +# +# # Customization Settings. +# # The following allows specifying custom Kubernetes metadata (labels and annotations) +# # for all objects instantiated by this Helm chart, as well as additional pod labels, +# # pod annotations, and container environment variables for workloads. +# # The configuration is hierarchical, in the sense that metadata that is defined at a more +# # generic scope (e.g., for all objects) can be overridden by metadata defined at a narrower +# # scope (e.g., only for the sensor deployment). +# customize: +# # Extra metadata for all objects. +# labels: +# my-label-key: my-label-value +# annotations: +# my-annotation-key: my-annotation-value +# +# # Extra pod metadata for all objects (only has an effect for workloads, i.e., deployments). +# podLabels: +# my-pod-label-key: my-pod-label-value +# podAnnotations: +# my-pod-annotation-key: my-pod-annotation-value +# +# # Extra environment variables for all containers in all objects. +# envVars: +# MY_ENV_VAR_NAME: MY_ENV_VAR_VALUE +# +# # Extra metadata for the Sensor deployment only. +# sensor: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the collector daemon set only. +# collector: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the admission control only. +# admission-control: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for the compliance only. +# compliance: +# labels: {} +# annotations: {} +# podLabels: {} +# podAnnotations: {} +# envVars: {} +# +# # Extra metadata for all other objects. The keys in the following map can be +# # an object name of the form "service/central-loadbalancer", or a reference to all +# # objects of a given type in the form "service/*". The values under each key +# # are the five metadata overrides (labels, annotations, podLabels, podAnnotations, envVars) +# # as specified above, though only the first two will be relevant for non-workload +# # object types. +# other: +# "service/*": +# labels: {} +# annotations: {} +# +# # EXPERT SETTINGS +# # The following settings should only be changed if you know very well what you are doing. +# # The scenarios in which these are required are generally not supported. +# +# # Set allowNonstandardNamespace=true if you are deploying into a namespace other than +# # "stackrox". This has been observed to work in some case, but is not generally supported. +# allowNonstandardNamespace: false +# +# # Set allowNonstandardReleaseName=true if you are deploying with a release name other than +# # the default "stackrox-central-services". This has been observed to work in some cases, +# # but is not generally supported. +# allowNonstandardReleaseName: false +# +# +#meta: +# # This is a dictionary from file names to contents that can be used to inject files that +# # would usually be included via .Files.Get into the chart rendering. +# fileOverrides: {} +# +# # This configuration section allows overriding settings that would be inferred from the +# # running API server. +# apiServer: +# # The Kubernetes version running on the API server. This is used for auto-detection +# # of the platform. +# version: null +# # The list of available API resources on the server, in the form of "apps/v1" or +# # "apps/v1/Deployment". This is used to detect environment capabilities. +# overrideAPIResources: null +# # A list of extra API resources that should be assumed to exist on the API server. This +# # can be used in conjunction with both data obtained from the API server, or data set +# # via `overrideAPIResources`. +# extraAPIResources: [] +# +#monitoring: +# # Enables integration with OpenShift platform monitoring. +# openshift: +# enabled: true diff --git a/rhacs/4.3.8/secured-cluster-services/values-scanner.yaml.example b/rhacs/4.3.8/secured-cluster-services/values-scanner.yaml.example new file mode 100644 index 0000000..c422153 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/values-scanner.yaml.example @@ -0,0 +1,92 @@ +# # NOTE: +# # The Scanner is only available in the secured clusters on the OpenShift Container Platform. +# +# # Public configuration options for the StackRox Scanner: +# # When installing the Secured Cluster chart, a slim scanner mode is deployed with reduced image caching. +# # To run the scanner in the secured cluster, you must connect the Scanner to Sensor. +# +# # WARNING: +# # If deployed in the same namespace with Central it is only supported to install Scanner as part of Central's installation. +# # Sensor will use the existing Scanner to scan for local images. +# +# Image configuration for scanner: +# # For a complete example, see the `values-public.yaml.example` file. +# image: +# # Configuration for the `scanner` image that is used by Scanner. +# scanner: +# registry: null +# name: scanner-slim +# tag: null +# fullRef: null +# +# scanner: +# # disable=false Deploys a StackRox Scanner in the secured cluster to allow scanning images +# # from the OpenShift Container Platform cluster's local registries. +# disable: false +# +# # The number of replicas for the Scanner deployment. If autoscaling is enabled (see below), +# # this determines the initial number of replicas. +# replicas: 3 +# +# # The log level for the scanner deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce StackRox Scanner to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-scanner +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# # If you want to enforce StackRox Scanner DB to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner DB can only be scheduled on Nodes with the +# # given label. +# dbNodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: stackrox-scanner-db +# +# If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# dbTolerations: +# - effect: NoSchedule +# key: infra +# value: reserved +# - effect: NoExecute +# key: infra +# value: reserved +# +# # Configuration for autoscaling the Scanner deployment. +# autoscaling: +# # disable=true causes autoscaling to be disabled. All other settings in this section +# # will have no effect. +# disable: false +# # The minimum number of replicas for autoscaling. The following value is the default. +# minReplicas: 2 +# # The maximum number of replicas for autoscaling. The following value is the default. +# maxReplicas: 5 +# +# # Custom resource overrides for the Scanner deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "4Gi" +# cpu: "2000m" +# +# # Custom resource overrides for the Scanner DB deployment. +# dbResources: +# limits: +# cpu: "2000m" +# memory: "4Gi" +# requests: +# cpu: "200m" +# memory: "200Mi" diff --git a/rhacs/4.3.8/secured-cluster-services/values.yaml b/rhacs/4.3.8/secured-cluster-services/values.yaml new file mode 100644 index 0000000..3297a22 --- /dev/null +++ b/rhacs/4.3.8/secured-cluster-services/values.yaml @@ -0,0 +1,9 @@ +## StackRox Secured Cluster Services chart +## values.yaml +## +## This file contains no values. In particular, you should NOT modify this file; instead, +## create your own configuration file and pass it to `helm` via the `-f` parameter. +## For this, you can use the files `values-private.yaml.example` and `values-public.yaml.example` +## that are part of the chart as a blueprint. +## +## Please also consult README.md for a list of available configuration options.