From 715cd52c1ce1a0310b679b7fdf1f0a46206eaf8a Mon Sep 17 00:00:00 2001 From: rhacs-bot Date: Mon, 16 Sep 2024 19:20:01 +0000 Subject: [PATCH] Publish Helm Charts for version 4.5.2 (#150) Source-Version: eb1194c2e8fd0a4b65f515627b80ff0deac5308c --- 4.5.2/central-services/.helmignore | 23 + 4.5.2/central-services/Chart.yaml | 7 + 4.5.2/central-services/README.md | 221 +++++ .../assets/Red_Hat-Hat_icon.png | Bin 0 -> 7393 bytes .../central-services/assets/StackRox_icon.png | Bin 0 -> 13406 bytes .../scanner-v4-db/pg_hba.conf.default | 23 + .../scanner-v4-db/postgresql.conf.default | 75 ++ .../scanner-v4/indexer-config.yaml.tpl | 47 ++ .../scanner-v4/matcher-config.yaml.tpl | 39 + .../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 | 27 + .../annotations/helm-hook_secret.yaml | 2 + .../annotations/helm-hook_storage.yaml | 3 + .../internal/bootstrap-defaults.yaml.tpl | 16 + .../internal/config-shape.yaml | 192 +++++ 4.5.2/central-services/internal/defaults.yaml | 331 ++++++++ .../internal/expandables.yaml | 71 ++ .../internal/platforms/default.yaml | 2 + .../internal/platforms/gke.yaml | 2 + .../internal/scanner-config-shape.yaml | 44 + .../internal/scanner-v4-config-shape.yaml | 79 ++ .../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 | 124 +++ .../templates/00-storage-class.yaml | 26 + .../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 | 80 ++ .../templates/01-central-02-db-security.yaml | 44 + .../templates/01-central-02-psps.yaml | 80 ++ .../templates/01-central-02-security.yaml | 44 + .../01-central-03-cloud-credentials-rbac.yaml | 34 + .../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 | 28 + .../01-central-10-networkpolicy.yaml | 67 ++ .../templates/01-central-11-db-pvc.yaml | 64 ++ .../templates/01-central-11-pvc.yaml | 61 ++ .../templates/01-central-12-central-db.yaml | 206 +++++ .../templates/01-central-13-deployment.yaml | 308 +++++++ .../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 | 45 + .../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 | 318 ++++++++ .../templates/02-scanner-07-service.yaml | 99 +++ .../templates/02-scanner-08-hpa.yaml | 25 + .../02-scanner-v4-00-serviceaccount.yaml | 16 + .../templates/02-scanner-v4-01-psps.yaml | 72 ++ .../templates/02-scanner-v4-01-security.yaml | 51 ++ .../02-scanner-v4-02-db-password-secret.yaml | 19 + .../02-scanner-v4-03-db-tls-secret.yaml | 22 + .../02-scanner-v4-03-indexer-tls-secret.yaml | 22 + .../02-scanner-v4-03-matcher-tls-secret.yaml | 22 + .../templates/02-scanner-v4-04-db-config.yaml | 17 + .../02-scanner-v4-04-indexer-config.yaml | 15 + .../02-scanner-v4-04-matcher-config.yaml | 15 + .../02-scanner-v4-05-db-network-policy.yaml | 39 + ...-scanner-v4-05-indexer-network-policy.yaml | 90 ++ ...-scanner-v4-05-matcher-network-policy.yaml | 74 ++ .../templates/02-scanner-v4-06-db-pvc.yaml | 66 ++ .../02-scanner-v4-07-db-deployment.yaml | 142 ++++ .../02-scanner-v4-07-indexer-deployment.yaml | 174 ++++ .../02-scanner-v4-07-matcher-deployment.yaml | 171 ++++ .../02-scanner-v4-08-db-service.yaml | 43 + .../02-scanner-v4-08-indexer-service.yaml | 55 ++ .../02-scanner-v4-08-matcher-service.yaml | 55 ++ .../02-scanner-v4-09-indexer-hpa.yaml | 20 + .../02-scanner-v4-09-matcher-hpa.yaml | 20 + .../templates/99-generated-values-secret.yaml | 25 + .../templates/99-openshift-monitoring.yaml | 149 ++++ .../99-shared-openshift-monitoring.yaml | 65 ++ 4.5.2/central-services/templates/NOTES.txt | 68 ++ .../templates/_central_endpoints.tpl | 59 ++ .../templates/_central_setup.tpl | 146 ++++ 4.5.2/central-services/templates/_crypto.tpl | 247 ++++++ 4.5.2/central-services/templates/_dict.tpl | 142 ++++ 4.5.2/central-services/templates/_expand.tpl | 96 +++ 4.5.2/central-services/templates/_format.tpl | 14 + 4.5.2/central-services/templates/_helpers.tpl | 94 +++ .../templates/_image-pull-secrets.tpl | 105 +++ 4.5.2/central-services/templates/_images.tpl | 34 + 4.5.2/central-services/templates/_init.tpl | 310 +++++++ .../templates/_injected-ca-bundle.tpl | 29 + 4.5.2/central-services/templates/_labels.tpl | 31 + 4.5.2/central-services/templates/_lookup.tpl | 40 + .../central-services/templates/_metadata.tpl | 307 +++++++ .../central-services/templates/_openshift.tpl | 47 ++ 4.5.2/central-services/templates/_psp.tpl | 19 + 4.5.2/central-services/templates/_pvcs.tpl | 20 + .../central-services/templates/_reporting.tpl | 34 + .../templates/_scanner-v4_init.tpl | 179 ++++ .../templates/_scanner-v4_volume.tpl | 113 +++ .../templates/_scanner_init.tpl | 40 + .../templates/_set_install_method.tpl | 13 + .../templates/_storage_classes.tpl | 36 + .../values-private.yaml.example | 224 +++++ .../values-public.yaml.example | 772 ++++++++++++++++++ 4.5.2/central-services/values.yaml | 578 +++++++++++++ 4.5.2/secured-cluster-services/.helmignore | 23 + 4.5.2/secured-cluster-services/Chart.yaml | 8 + 4.5.2/secured-cluster-services/README.md | 474 +++++++++++ .../assets/Red_Hat-Hat_icon.png | Bin 0 -> 7393 bytes .../assets/StackRox_icon.png | Bin 0 -> 13406 bytes .../scanner-v4-db/pg_hba.conf.default | 23 + .../scanner-v4-db/postgresql.conf.default | 75 ++ .../scanner-v4/indexer-config.yaml.tpl | 47 ++ .../scanner-v4/matcher-config.yaml.tpl | 39 + .../config-templates/scanner/config.yaml.tpl | 48 ++ .../annotations/helm-hook_secret.yaml | 2 + .../annotations/helm-hook_storage.yaml | 3 + .../internal/cluster-config.yaml.tpl | 33 + .../internal/compatibility-translation.yaml | 137 ++++ .../internal/config-shape.yaml | 198 +++++ .../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 | 120 +++ .../internal/defaults/40-resources.yaml | 44 + .../internal/defaults/50-images.yaml | 124 +++ .../internal/defaults/70-scanner-v4.yaml | 105 +++ .../internal/defaults/70-scanner.yaml | 38 + .../internal/defaults/whats-this.md | 39 + .../internal/expandables.yaml | 61 ++ .../internal/scanner-config-shape.yaml | 44 + .../internal/scanner-v4-config-shape.yaml | 79 ++ .../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 + .../templates/00-storage-class.yaml | 26 + .../02-scanner-00-serviceaccount.yaml | 19 + .../templates/02-scanner-01-psps.yaml | 69 ++ .../templates/02-scanner-01-security.yaml | 45 + .../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 | 318 ++++++++ .../templates/02-scanner-07-service.yaml | 99 +++ .../templates/02-scanner-08-hpa.yaml | 25 + .../02-scanner-v4-00-serviceaccount.yaml | 16 + .../templates/02-scanner-v4-01-psps.yaml | 72 ++ .../templates/02-scanner-v4-01-security.yaml | 51 ++ .../02-scanner-v4-02-db-password-secret.yaml | 19 + .../templates/02-scanner-v4-04-db-config.yaml | 17 + .../02-scanner-v4-04-indexer-config.yaml | 15 + .../02-scanner-v4-05-db-network-policy.yaml | 39 + ...-scanner-v4-05-indexer-network-policy.yaml | 90 ++ .../templates/02-scanner-v4-06-db-pvc.yaml | 66 ++ .../02-scanner-v4-07-db-deployment.yaml | 142 ++++ .../02-scanner-v4-07-indexer-deployment.yaml | 174 ++++ .../02-scanner-v4-08-db-service.yaml | 43 + .../02-scanner-v4-08-indexer-service.yaml | 55 ++ .../02-scanner-v4-09-indexer-hpa.yaml | 20 + .../99-shared-openshift-monitoring.yaml | 65 ++ .../templates/NOTES.txt | 44 + .../templates/_compatibility.tpl | 51 ++ .../templates/_crypto.tpl | 247 ++++++ .../templates/_defaults.tpl | 58 ++ .../templates/_dict.tpl | 142 ++++ .../templates/_expand.tpl | 96 +++ .../templates/_format.tpl | 14 + .../templates/_helpers.tpl | 94 +++ .../templates/_image-pull-secrets.tpl | 105 +++ .../templates/_images.tpl | 34 + .../templates/_init.tpl | 330 ++++++++ .../templates/_injected-ca-bundle.tpl | 29 + .../templates/_labels.tpl | 31 + .../templates/_lookup.tpl | 40 + .../templates/_metadata.tpl | 307 +++++++ .../templates/_openshift.tpl | 47 ++ .../templates/_psp.tpl | 19 + .../templates/_pvcs.tpl | 20 + .../templates/_reporting.tpl | 34 + .../templates/_scanner-v4_init.tpl | 179 ++++ .../templates/_scanner-v4_volume.tpl | 113 +++ .../templates/_scanner_init.tpl | 40 + .../templates/_set_install_method.tpl | 13 + .../templates/_storage_classes.tpl | 36 + .../templates/additional-ca-sensor.yaml | 19 + .../admission-controller-netpol.yaml | 48 ++ .../admission-controller-pod-security.yaml | 76 ++ .../templates/admission-controller-rbac.yaml | 50 ++ .../admission-controller-secret.yaml | 30 + .../templates/admission-controller.yaml | 256 ++++++ .../templates/cluster-config.yaml | 14 + .../templates/collector-netpol.yaml | 46 ++ .../templates/collector-pod-security.yaml | 72 ++ .../templates/collector-rbac.yaml | 16 + .../templates/collector-scc.yaml | 49 ++ .../templates/collector-secret.yaml | 30 + .../templates/collector.yaml | 234 ++++++ .../templates/openshift-monitoring.yaml | 136 +++ .../templates/sensor-compliance-rbac.yaml | 36 + .../templates/sensor-netpol.yaml | 95 +++ .../templates/sensor-pod-security.yaml | 82 ++ .../templates/sensor-rbac.yaml | 293 +++++++ .../templates/sensor-secret.yaml | 30 + .../templates/sensor.yaml | 308 +++++++ .../templates/service-ca.yaml | 16 + .../templates/upgrader-serviceaccount.yaml | 36 + .../values-private-scanner-v4.yaml.example | 37 + .../values-private.yaml.example | 19 + .../values-public-scanner-v4.yaml.example | 177 ++++ .../values-public.yaml.example | 462 +++++++++++ .../values-scanner.yaml.example | 92 +++ 4.5.2/secured-cluster-services/values.yaml | 9 + README.md | 4 +- latest | 2 +- opensource/index.yaml | 268 +++--- .../stackrox-central-services-400.5.2.tgz | Bin 0 -> 90876 bytes ...ckrox-secured-cluster-services-400.5.2.tgz | Bin 0 -> 90907 bytes rhacs/4.5.2/central-services/.helmignore | 23 + rhacs/4.5.2/central-services/Chart.yaml | 7 + rhacs/4.5.2/central-services/README.md | 221 +++++ .../assets/Red_Hat-Hat_icon.png | Bin 0 -> 7393 bytes .../central-services/assets/StackRox_icon.png | Bin 0 -> 13406 bytes .../scanner-v4-db/pg_hba.conf.default | 23 + .../scanner-v4-db/postgresql.conf.default | 75 ++ .../scanner-v4/indexer-config.yaml.tpl | 47 ++ .../scanner-v4/matcher-config.yaml.tpl | 39 + .../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 | 27 + .../annotations/helm-hook_secret.yaml | 2 + .../annotations/helm-hook_storage.yaml | 3 + .../internal/bootstrap-defaults.yaml.tpl | 16 + .../internal/config-shape.yaml | 192 +++++ .../central-services/internal/defaults.yaml | 331 ++++++++ .../internal/expandables.yaml | 71 ++ .../internal/platforms/default.yaml | 2 + .../internal/platforms/gke.yaml | 2 + .../internal/scanner-config-shape.yaml | 44 + .../internal/scanner-v4-config-shape.yaml | 79 ++ .../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 | 124 +++ .../templates/00-storage-class.yaml | 26 + .../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 | 80 ++ .../templates/01-central-02-db-security.yaml | 44 + .../templates/01-central-02-psps.yaml | 80 ++ .../templates/01-central-02-security.yaml | 44 + .../01-central-03-cloud-credentials-rbac.yaml | 34 + .../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 | 28 + .../01-central-10-networkpolicy.yaml | 67 ++ .../templates/01-central-11-db-pvc.yaml | 64 ++ .../templates/01-central-11-pvc.yaml | 61 ++ .../templates/01-central-12-central-db.yaml | 206 +++++ .../templates/01-central-13-deployment.yaml | 308 +++++++ .../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 | 45 + .../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 | 318 ++++++++ .../templates/02-scanner-07-service.yaml | 99 +++ .../templates/02-scanner-08-hpa.yaml | 25 + .../02-scanner-v4-00-serviceaccount.yaml | 16 + .../templates/02-scanner-v4-01-psps.yaml | 72 ++ .../templates/02-scanner-v4-01-security.yaml | 51 ++ .../02-scanner-v4-02-db-password-secret.yaml | 19 + .../02-scanner-v4-03-db-tls-secret.yaml | 22 + .../02-scanner-v4-03-indexer-tls-secret.yaml | 22 + .../02-scanner-v4-03-matcher-tls-secret.yaml | 22 + .../templates/02-scanner-v4-04-db-config.yaml | 17 + .../02-scanner-v4-04-indexer-config.yaml | 15 + .../02-scanner-v4-04-matcher-config.yaml | 15 + .../02-scanner-v4-05-db-network-policy.yaml | 39 + ...-scanner-v4-05-indexer-network-policy.yaml | 90 ++ ...-scanner-v4-05-matcher-network-policy.yaml | 74 ++ .../templates/02-scanner-v4-06-db-pvc.yaml | 66 ++ .../02-scanner-v4-07-db-deployment.yaml | 142 ++++ .../02-scanner-v4-07-indexer-deployment.yaml | 174 ++++ .../02-scanner-v4-07-matcher-deployment.yaml | 171 ++++ .../02-scanner-v4-08-db-service.yaml | 43 + .../02-scanner-v4-08-indexer-service.yaml | 55 ++ .../02-scanner-v4-08-matcher-service.yaml | 55 ++ .../02-scanner-v4-09-indexer-hpa.yaml | 20 + .../02-scanner-v4-09-matcher-hpa.yaml | 20 + .../templates/99-generated-values-secret.yaml | 25 + .../templates/99-openshift-monitoring.yaml | 149 ++++ .../99-shared-openshift-monitoring.yaml | 65 ++ .../central-services/templates/NOTES.txt | 68 ++ .../templates/_central_endpoints.tpl | 59 ++ .../templates/_central_setup.tpl | 146 ++++ .../central-services/templates/_crypto.tpl | 247 ++++++ .../central-services/templates/_dict.tpl | 142 ++++ .../central-services/templates/_expand.tpl | 96 +++ .../central-services/templates/_format.tpl | 14 + .../central-services/templates/_helpers.tpl | 94 +++ .../templates/_image-pull-secrets.tpl | 105 +++ .../central-services/templates/_images.tpl | 34 + .../central-services/templates/_init.tpl | 310 +++++++ .../templates/_injected-ca-bundle.tpl | 29 + .../central-services/templates/_labels.tpl | 31 + .../central-services/templates/_lookup.tpl | 40 + .../central-services/templates/_metadata.tpl | 307 +++++++ .../central-services/templates/_openshift.tpl | 47 ++ .../4.5.2/central-services/templates/_psp.tpl | 19 + .../central-services/templates/_pvcs.tpl | 20 + .../central-services/templates/_reporting.tpl | 34 + .../templates/_scanner-v4_init.tpl | 179 ++++ .../templates/_scanner-v4_volume.tpl | 113 +++ .../templates/_scanner_init.tpl | 40 + .../templates/_set_install_method.tpl | 13 + .../templates/_storage_classes.tpl | 36 + .../values-private.yaml.example | 224 +++++ .../values-public.yaml.example | 772 ++++++++++++++++++ rhacs/4.5.2/central-services/values.yaml | 578 +++++++++++++ .../secured-cluster-services/.helmignore | 23 + .../4.5.2/secured-cluster-services/Chart.yaml | 8 + .../4.5.2/secured-cluster-services/README.md | 474 +++++++++++ .../assets/Red_Hat-Hat_icon.png | Bin 0 -> 7393 bytes .../assets/StackRox_icon.png | Bin 0 -> 13406 bytes .../scanner-v4-db/pg_hba.conf.default | 23 + .../scanner-v4-db/postgresql.conf.default | 75 ++ .../scanner-v4/indexer-config.yaml.tpl | 47 ++ .../scanner-v4/matcher-config.yaml.tpl | 39 + .../config-templates/scanner/config.yaml.tpl | 48 ++ .../annotations/helm-hook_secret.yaml | 2 + .../annotations/helm-hook_storage.yaml | 3 + .../internal/cluster-config.yaml.tpl | 33 + .../internal/compatibility-translation.yaml | 137 ++++ .../internal/config-shape.yaml | 198 +++++ .../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 | 120 +++ .../internal/defaults/40-resources.yaml | 44 + .../internal/defaults/50-images.yaml | 124 +++ .../internal/defaults/70-scanner-v4.yaml | 105 +++ .../internal/defaults/70-scanner.yaml | 38 + .../internal/defaults/whats-this.md | 39 + .../internal/expandables.yaml | 61 ++ .../internal/scanner-config-shape.yaml | 44 + .../internal/scanner-v4-config-shape.yaml | 79 ++ .../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 + .../templates/00-storage-class.yaml | 26 + .../02-scanner-00-serviceaccount.yaml | 19 + .../templates/02-scanner-01-psps.yaml | 69 ++ .../templates/02-scanner-01-security.yaml | 45 + .../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 | 318 ++++++++ .../templates/02-scanner-07-service.yaml | 99 +++ .../templates/02-scanner-08-hpa.yaml | 25 + .../02-scanner-v4-00-serviceaccount.yaml | 16 + .../templates/02-scanner-v4-01-psps.yaml | 72 ++ .../templates/02-scanner-v4-01-security.yaml | 51 ++ .../02-scanner-v4-02-db-password-secret.yaml | 19 + .../templates/02-scanner-v4-04-db-config.yaml | 17 + .../02-scanner-v4-04-indexer-config.yaml | 15 + .../02-scanner-v4-05-db-network-policy.yaml | 39 + ...-scanner-v4-05-indexer-network-policy.yaml | 90 ++ .../templates/02-scanner-v4-06-db-pvc.yaml | 66 ++ .../02-scanner-v4-07-db-deployment.yaml | 142 ++++ .../02-scanner-v4-07-indexer-deployment.yaml | 174 ++++ .../02-scanner-v4-08-db-service.yaml | 43 + .../02-scanner-v4-08-indexer-service.yaml | 55 ++ .../02-scanner-v4-09-indexer-hpa.yaml | 20 + .../99-shared-openshift-monitoring.yaml | 65 ++ .../templates/NOTES.txt | 44 + .../templates/_compatibility.tpl | 51 ++ .../templates/_crypto.tpl | 247 ++++++ .../templates/_defaults.tpl | 58 ++ .../templates/_dict.tpl | 142 ++++ .../templates/_expand.tpl | 96 +++ .../templates/_format.tpl | 14 + .../templates/_helpers.tpl | 94 +++ .../templates/_image-pull-secrets.tpl | 105 +++ .../templates/_images.tpl | 34 + .../templates/_init.tpl | 330 ++++++++ .../templates/_injected-ca-bundle.tpl | 29 + .../templates/_labels.tpl | 31 + .../templates/_lookup.tpl | 40 + .../templates/_metadata.tpl | 307 +++++++ .../templates/_openshift.tpl | 47 ++ .../templates/_psp.tpl | 19 + .../templates/_pvcs.tpl | 20 + .../templates/_reporting.tpl | 34 + .../templates/_scanner-v4_init.tpl | 179 ++++ .../templates/_scanner-v4_volume.tpl | 113 +++ .../templates/_scanner_init.tpl | 40 + .../templates/_set_install_method.tpl | 13 + .../templates/_storage_classes.tpl | 36 + .../templates/additional-ca-sensor.yaml | 19 + .../admission-controller-netpol.yaml | 48 ++ .../admission-controller-pod-security.yaml | 76 ++ .../templates/admission-controller-rbac.yaml | 50 ++ .../admission-controller-secret.yaml | 30 + .../templates/admission-controller.yaml | 256 ++++++ .../templates/cluster-config.yaml | 14 + .../templates/collector-netpol.yaml | 46 ++ .../templates/collector-pod-security.yaml | 72 ++ .../templates/collector-rbac.yaml | 16 + .../templates/collector-scc.yaml | 49 ++ .../templates/collector-secret.yaml | 30 + .../templates/collector.yaml | 234 ++++++ .../templates/openshift-monitoring.yaml | 136 +++ .../templates/sensor-compliance-rbac.yaml | 36 + .../templates/sensor-netpol.yaml | 95 +++ .../templates/sensor-pod-security.yaml | 82 ++ .../templates/sensor-rbac.yaml | 293 +++++++ .../templates/sensor-secret.yaml | 30 + .../templates/sensor.yaml | 308 +++++++ .../templates/service-ca.yaml | 16 + .../templates/upgrader-serviceaccount.yaml | 36 + .../values-private-scanner-v4.yaml.example | 37 + .../values-private.yaml.example | 19 + .../values-public-scanner-v4.yaml.example | 177 ++++ .../values-public.yaml.example | 462 +++++++++++ .../values-scanner.yaml.example | 92 +++ .../secured-cluster-services/values.yaml | 9 + 463 files changed, 35582 insertions(+), 126 deletions(-) create mode 100644 4.5.2/central-services/.helmignore create mode 100644 4.5.2/central-services/Chart.yaml create mode 100644 4.5.2/central-services/README.md create mode 100644 4.5.2/central-services/assets/Red_Hat-Hat_icon.png create mode 100644 4.5.2/central-services/assets/StackRox_icon.png create mode 100644 4.5.2/central-services/config-templates/scanner-v4-db/pg_hba.conf.default create mode 100644 4.5.2/central-services/config-templates/scanner-v4-db/postgresql.conf.default create mode 100644 4.5.2/central-services/config-templates/scanner-v4/indexer-config.yaml.tpl create mode 100644 4.5.2/central-services/config-templates/scanner-v4/matcher-config.yaml.tpl create mode 100644 4.5.2/central-services/config-templates/scanner/config.yaml.tpl create mode 100644 4.5.2/central-services/config/central/config.yaml.default create mode 100644 4.5.2/central-services/config/central/endpoints.yaml.default create mode 100644 4.5.2/central-services/config/centraldb/pg_hba.conf.default create mode 100644 4.5.2/central-services/config/centraldb/postgresql.conf.default create mode 100644 4.5.2/central-services/config/proxy-config.yaml.default create mode 100644 4.5.2/central-services/internal/annotations/helm-hook_secret.yaml create mode 100644 4.5.2/central-services/internal/annotations/helm-hook_storage.yaml create mode 100644 4.5.2/central-services/internal/bootstrap-defaults.yaml.tpl create mode 100644 4.5.2/central-services/internal/config-shape.yaml create mode 100644 4.5.2/central-services/internal/defaults.yaml create mode 100644 4.5.2/central-services/internal/expandables.yaml create mode 100644 4.5.2/central-services/internal/platforms/default.yaml create mode 100644 4.5.2/central-services/internal/platforms/gke.yaml create mode 100644 4.5.2/central-services/internal/scanner-config-shape.yaml create mode 100644 4.5.2/central-services/internal/scanner-v4-config-shape.yaml create mode 100644 4.5.2/central-services/templates/00-additional-ca.yaml create mode 100644 4.5.2/central-services/templates/00-image-pull-secret.yaml create mode 100644 4.5.2/central-services/templates/00-injected-ca-bundle.yaml create mode 100644 4.5.2/central-services/templates/00-proxy-config-secret.yaml create mode 100644 4.5.2/central-services/templates/00-stackrox-application.yaml create mode 100644 4.5.2/central-services/templates/00-storage-class.yaml create mode 100644 4.5.2/central-services/templates/01-central-00-db-serviceaccount.yaml create mode 100644 4.5.2/central-services/templates/01-central-00-serviceaccount.yaml create mode 100644 4.5.2/central-services/templates/01-central-01-license-secret.yaml create mode 100644 4.5.2/central-services/templates/01-central-02-db-psps.yaml create mode 100644 4.5.2/central-services/templates/01-central-02-db-security.yaml create mode 100644 4.5.2/central-services/templates/01-central-02-psps.yaml create mode 100644 4.5.2/central-services/templates/01-central-02-security.yaml create mode 100644 4.5.2/central-services/templates/01-central-03-cloud-credentials-rbac.yaml create mode 100644 4.5.2/central-services/templates/01-central-03-diagnostics-rbac.yaml create mode 100644 4.5.2/central-services/templates/01-central-04-htpasswd-secret.yaml create mode 100644 4.5.2/central-services/templates/01-central-05-db-tls-secret.yaml create mode 100644 4.5.2/central-services/templates/01-central-05-tls-secret.yaml create mode 100644 4.5.2/central-services/templates/01-central-06-default-tls-cert-secret.yaml create mode 100644 4.5.2/central-services/templates/01-central-08-configmap.yaml create mode 100644 4.5.2/central-services/templates/01-central-08-db-configmap.yaml create mode 100644 4.5.2/central-services/templates/01-central-08-external-db-configmap.yaml create mode 100644 4.5.2/central-services/templates/01-central-09-endpoints-config.yaml create mode 100644 4.5.2/central-services/templates/01-central-10-db-networkpolicy.yaml create mode 100644 4.5.2/central-services/templates/01-central-10-networkpolicy.yaml create mode 100644 4.5.2/central-services/templates/01-central-11-db-pvc.yaml create mode 100644 4.5.2/central-services/templates/01-central-11-pvc.yaml create mode 100644 4.5.2/central-services/templates/01-central-12-central-db.yaml create mode 100644 4.5.2/central-services/templates/01-central-13-deployment.yaml create mode 100644 4.5.2/central-services/templates/01-central-14-service.yaml create mode 100644 4.5.2/central-services/templates/01-central-15-exposure.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-00-serviceaccount.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-01-psps.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-01-security.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-02-db-password-secret.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-03-tls-secret.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-04-scanner-config.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-05-network-policy.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-06-deployment.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-07-service.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-08-hpa.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-00-serviceaccount.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-01-psps.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-01-security.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-02-db-password-secret.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-03-db-tls-secret.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-03-indexer-tls-secret.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-03-matcher-tls-secret.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-04-db-config.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-04-indexer-config.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-04-matcher-config.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-05-db-network-policy.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-05-indexer-network-policy.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-05-matcher-network-policy.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-06-db-pvc.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-07-db-deployment.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-07-indexer-deployment.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-07-matcher-deployment.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-08-db-service.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-08-indexer-service.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-08-matcher-service.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-09-indexer-hpa.yaml create mode 100644 4.5.2/central-services/templates/02-scanner-v4-09-matcher-hpa.yaml create mode 100644 4.5.2/central-services/templates/99-generated-values-secret.yaml create mode 100644 4.5.2/central-services/templates/99-openshift-monitoring.yaml create mode 100644 4.5.2/central-services/templates/99-shared-openshift-monitoring.yaml create mode 100644 4.5.2/central-services/templates/NOTES.txt create mode 100644 4.5.2/central-services/templates/_central_endpoints.tpl create mode 100644 4.5.2/central-services/templates/_central_setup.tpl create mode 100644 4.5.2/central-services/templates/_crypto.tpl create mode 100644 4.5.2/central-services/templates/_dict.tpl create mode 100644 4.5.2/central-services/templates/_expand.tpl create mode 100644 4.5.2/central-services/templates/_format.tpl create mode 100644 4.5.2/central-services/templates/_helpers.tpl create mode 100644 4.5.2/central-services/templates/_image-pull-secrets.tpl create mode 100644 4.5.2/central-services/templates/_images.tpl create mode 100644 4.5.2/central-services/templates/_init.tpl create mode 100644 4.5.2/central-services/templates/_injected-ca-bundle.tpl create mode 100644 4.5.2/central-services/templates/_labels.tpl create mode 100644 4.5.2/central-services/templates/_lookup.tpl create mode 100644 4.5.2/central-services/templates/_metadata.tpl create mode 100644 4.5.2/central-services/templates/_openshift.tpl create mode 100644 4.5.2/central-services/templates/_psp.tpl create mode 100644 4.5.2/central-services/templates/_pvcs.tpl create mode 100644 4.5.2/central-services/templates/_reporting.tpl create mode 100644 4.5.2/central-services/templates/_scanner-v4_init.tpl create mode 100644 4.5.2/central-services/templates/_scanner-v4_volume.tpl create mode 100644 4.5.2/central-services/templates/_scanner_init.tpl create mode 100644 4.5.2/central-services/templates/_set_install_method.tpl create mode 100644 4.5.2/central-services/templates/_storage_classes.tpl create mode 100644 4.5.2/central-services/values-private.yaml.example create mode 100644 4.5.2/central-services/values-public.yaml.example create mode 100644 4.5.2/central-services/values.yaml create mode 100644 4.5.2/secured-cluster-services/.helmignore create mode 100644 4.5.2/secured-cluster-services/Chart.yaml create mode 100644 4.5.2/secured-cluster-services/README.md create mode 100644 4.5.2/secured-cluster-services/assets/Red_Hat-Hat_icon.png create mode 100644 4.5.2/secured-cluster-services/assets/StackRox_icon.png create mode 100644 4.5.2/secured-cluster-services/config-templates/scanner-v4-db/pg_hba.conf.default create mode 100644 4.5.2/secured-cluster-services/config-templates/scanner-v4-db/postgresql.conf.default create mode 100644 4.5.2/secured-cluster-services/config-templates/scanner-v4/indexer-config.yaml.tpl create mode 100644 4.5.2/secured-cluster-services/config-templates/scanner-v4/matcher-config.yaml.tpl create mode 100644 4.5.2/secured-cluster-services/config-templates/scanner/config.yaml.tpl create mode 100644 4.5.2/secured-cluster-services/internal/annotations/helm-hook_secret.yaml create mode 100644 4.5.2/secured-cluster-services/internal/annotations/helm-hook_storage.yaml create mode 100644 4.5.2/secured-cluster-services/internal/cluster-config.yaml.tpl create mode 100644 4.5.2/secured-cluster-services/internal/compatibility-translation.yaml create mode 100644 4.5.2/secured-cluster-services/internal/config-shape.yaml create mode 100644 4.5.2/secured-cluster-services/internal/defaults/00-bootstrap.yaml create mode 100644 4.5.2/secured-cluster-services/internal/defaults/10-env.yaml create mode 100644 4.5.2/secured-cluster-services/internal/defaults/20-tls-files.yaml create mode 100644 4.5.2/secured-cluster-services/internal/defaults/30-base-config.yaml create mode 100644 4.5.2/secured-cluster-services/internal/defaults/40-resources.yaml create mode 100644 4.5.2/secured-cluster-services/internal/defaults/50-images.yaml create mode 100644 4.5.2/secured-cluster-services/internal/defaults/70-scanner-v4.yaml create mode 100644 4.5.2/secured-cluster-services/internal/defaults/70-scanner.yaml create mode 100644 4.5.2/secured-cluster-services/internal/defaults/whats-this.md create mode 100644 4.5.2/secured-cluster-services/internal/expandables.yaml create mode 100644 4.5.2/secured-cluster-services/internal/scanner-config-shape.yaml create mode 100644 4.5.2/secured-cluster-services/internal/scanner-v4-config-shape.yaml create mode 100755 4.5.2/secured-cluster-services/scripts/fetch-secrets.sh create mode 100644 4.5.2/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl create mode 100644 4.5.2/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl create mode 100644 4.5.2/secured-cluster-services/sensor-chart-upgrade.md create mode 100644 4.5.2/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml create mode 100644 4.5.2/secured-cluster-services/templates/00-injected-ca-bundle.yaml create mode 100644 4.5.2/secured-cluster-services/templates/00-main-image-pull-secrets.yaml create mode 100644 4.5.2/secured-cluster-services/templates/00-storage-class.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-01-psps.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-01-security.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-05-network-policy.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-06-deployment.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-07-service.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-08-hpa.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-00-serviceaccount.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-01-psps.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-01-security.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-02-db-password-secret.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-04-db-config.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-04-indexer-config.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-05-db-network-policy.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-05-indexer-network-policy.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-06-db-pvc.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-07-db-deployment.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-07-indexer-deployment.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-08-db-service.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-08-indexer-service.yaml create mode 100644 4.5.2/secured-cluster-services/templates/02-scanner-v4-09-indexer-hpa.yaml create mode 100644 4.5.2/secured-cluster-services/templates/99-shared-openshift-monitoring.yaml create mode 100644 4.5.2/secured-cluster-services/templates/NOTES.txt create mode 100644 4.5.2/secured-cluster-services/templates/_compatibility.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_crypto.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_defaults.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_dict.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_expand.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_format.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_helpers.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_image-pull-secrets.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_images.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_init.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_injected-ca-bundle.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_labels.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_lookup.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_metadata.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_openshift.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_psp.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_pvcs.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_reporting.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_scanner-v4_init.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_scanner-v4_volume.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_scanner_init.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_set_install_method.tpl create mode 100644 4.5.2/secured-cluster-services/templates/_storage_classes.tpl create mode 100644 4.5.2/secured-cluster-services/templates/additional-ca-sensor.yaml create mode 100644 4.5.2/secured-cluster-services/templates/admission-controller-netpol.yaml create mode 100644 4.5.2/secured-cluster-services/templates/admission-controller-pod-security.yaml create mode 100644 4.5.2/secured-cluster-services/templates/admission-controller-rbac.yaml create mode 100644 4.5.2/secured-cluster-services/templates/admission-controller-secret.yaml create mode 100644 4.5.2/secured-cluster-services/templates/admission-controller.yaml create mode 100644 4.5.2/secured-cluster-services/templates/cluster-config.yaml create mode 100644 4.5.2/secured-cluster-services/templates/collector-netpol.yaml create mode 100644 4.5.2/secured-cluster-services/templates/collector-pod-security.yaml create mode 100644 4.5.2/secured-cluster-services/templates/collector-rbac.yaml create mode 100644 4.5.2/secured-cluster-services/templates/collector-scc.yaml create mode 100644 4.5.2/secured-cluster-services/templates/collector-secret.yaml create mode 100644 4.5.2/secured-cluster-services/templates/collector.yaml create mode 100644 4.5.2/secured-cluster-services/templates/openshift-monitoring.yaml create mode 100644 4.5.2/secured-cluster-services/templates/sensor-compliance-rbac.yaml create mode 100644 4.5.2/secured-cluster-services/templates/sensor-netpol.yaml create mode 100644 4.5.2/secured-cluster-services/templates/sensor-pod-security.yaml create mode 100644 4.5.2/secured-cluster-services/templates/sensor-rbac.yaml create mode 100644 4.5.2/secured-cluster-services/templates/sensor-secret.yaml create mode 100644 4.5.2/secured-cluster-services/templates/sensor.yaml create mode 100644 4.5.2/secured-cluster-services/templates/service-ca.yaml create mode 100644 4.5.2/secured-cluster-services/templates/upgrader-serviceaccount.yaml create mode 100644 4.5.2/secured-cluster-services/values-private-scanner-v4.yaml.example create mode 100644 4.5.2/secured-cluster-services/values-private.yaml.example create mode 100644 4.5.2/secured-cluster-services/values-public-scanner-v4.yaml.example create mode 100644 4.5.2/secured-cluster-services/values-public.yaml.example create mode 100644 4.5.2/secured-cluster-services/values-scanner.yaml.example create mode 100644 4.5.2/secured-cluster-services/values.yaml create mode 100644 opensource/stackrox-central-services-400.5.2.tgz create mode 100644 opensource/stackrox-secured-cluster-services-400.5.2.tgz create mode 100644 rhacs/4.5.2/central-services/.helmignore create mode 100644 rhacs/4.5.2/central-services/Chart.yaml create mode 100644 rhacs/4.5.2/central-services/README.md create mode 100644 rhacs/4.5.2/central-services/assets/Red_Hat-Hat_icon.png create mode 100644 rhacs/4.5.2/central-services/assets/StackRox_icon.png create mode 100644 rhacs/4.5.2/central-services/config-templates/scanner-v4-db/pg_hba.conf.default create mode 100644 rhacs/4.5.2/central-services/config-templates/scanner-v4-db/postgresql.conf.default create mode 100644 rhacs/4.5.2/central-services/config-templates/scanner-v4/indexer-config.yaml.tpl create mode 100644 rhacs/4.5.2/central-services/config-templates/scanner-v4/matcher-config.yaml.tpl create mode 100644 rhacs/4.5.2/central-services/config-templates/scanner/config.yaml.tpl create mode 100644 rhacs/4.5.2/central-services/config/central/config.yaml.default create mode 100644 rhacs/4.5.2/central-services/config/central/endpoints.yaml.default create mode 100644 rhacs/4.5.2/central-services/config/centraldb/pg_hba.conf.default create mode 100644 rhacs/4.5.2/central-services/config/centraldb/postgresql.conf.default create mode 100644 rhacs/4.5.2/central-services/config/proxy-config.yaml.default create mode 100644 rhacs/4.5.2/central-services/internal/annotations/helm-hook_secret.yaml create mode 100644 rhacs/4.5.2/central-services/internal/annotations/helm-hook_storage.yaml create mode 100644 rhacs/4.5.2/central-services/internal/bootstrap-defaults.yaml.tpl create mode 100644 rhacs/4.5.2/central-services/internal/config-shape.yaml create mode 100644 rhacs/4.5.2/central-services/internal/defaults.yaml create mode 100644 rhacs/4.5.2/central-services/internal/expandables.yaml create mode 100644 rhacs/4.5.2/central-services/internal/platforms/default.yaml create mode 100644 rhacs/4.5.2/central-services/internal/platforms/gke.yaml create mode 100644 rhacs/4.5.2/central-services/internal/scanner-config-shape.yaml create mode 100644 rhacs/4.5.2/central-services/internal/scanner-v4-config-shape.yaml create mode 100644 rhacs/4.5.2/central-services/templates/00-additional-ca.yaml create mode 100644 rhacs/4.5.2/central-services/templates/00-image-pull-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/00-injected-ca-bundle.yaml create mode 100644 rhacs/4.5.2/central-services/templates/00-proxy-config-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/00-stackrox-application.yaml create mode 100644 rhacs/4.5.2/central-services/templates/00-storage-class.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-00-db-serviceaccount.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-00-serviceaccount.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-01-license-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-02-db-psps.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-02-db-security.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-02-psps.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-02-security.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-03-cloud-credentials-rbac.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-03-diagnostics-rbac.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-04-htpasswd-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-05-db-tls-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-05-tls-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-06-default-tls-cert-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-08-configmap.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-08-db-configmap.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-08-external-db-configmap.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-09-endpoints-config.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-10-db-networkpolicy.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-10-networkpolicy.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-11-db-pvc.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-11-pvc.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-12-central-db.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-13-deployment.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-14-service.yaml create mode 100644 rhacs/4.5.2/central-services/templates/01-central-15-exposure.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-00-serviceaccount.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-01-psps.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-01-security.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-02-db-password-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-03-tls-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-04-scanner-config.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-05-network-policy.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-06-deployment.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-07-service.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-08-hpa.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-00-serviceaccount.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-01-psps.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-01-security.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-02-db-password-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-03-db-tls-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-03-indexer-tls-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-03-matcher-tls-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-04-db-config.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-04-indexer-config.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-04-matcher-config.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-05-db-network-policy.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-05-indexer-network-policy.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-05-matcher-network-policy.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-06-db-pvc.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-07-db-deployment.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-07-indexer-deployment.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-07-matcher-deployment.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-08-db-service.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-08-indexer-service.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-08-matcher-service.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-09-indexer-hpa.yaml create mode 100644 rhacs/4.5.2/central-services/templates/02-scanner-v4-09-matcher-hpa.yaml create mode 100644 rhacs/4.5.2/central-services/templates/99-generated-values-secret.yaml create mode 100644 rhacs/4.5.2/central-services/templates/99-openshift-monitoring.yaml create mode 100644 rhacs/4.5.2/central-services/templates/99-shared-openshift-monitoring.yaml create mode 100644 rhacs/4.5.2/central-services/templates/NOTES.txt create mode 100644 rhacs/4.5.2/central-services/templates/_central_endpoints.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_central_setup.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_crypto.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_dict.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_expand.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_format.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_helpers.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_image-pull-secrets.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_images.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_init.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_injected-ca-bundle.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_labels.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_lookup.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_metadata.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_openshift.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_psp.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_pvcs.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_reporting.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_scanner-v4_init.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_scanner-v4_volume.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_scanner_init.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_set_install_method.tpl create mode 100644 rhacs/4.5.2/central-services/templates/_storage_classes.tpl create mode 100644 rhacs/4.5.2/central-services/values-private.yaml.example create mode 100644 rhacs/4.5.2/central-services/values-public.yaml.example create mode 100644 rhacs/4.5.2/central-services/values.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/.helmignore create mode 100644 rhacs/4.5.2/secured-cluster-services/Chart.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/README.md create mode 100644 rhacs/4.5.2/secured-cluster-services/assets/Red_Hat-Hat_icon.png create mode 100644 rhacs/4.5.2/secured-cluster-services/assets/StackRox_icon.png create mode 100644 rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/pg_hba.conf.default create mode 100644 rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/postgresql.conf.default create mode 100644 rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4/indexer-config.yaml.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4/matcher-config.yaml.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/config-templates/scanner/config.yaml.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/annotations/helm-hook_secret.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/annotations/helm-hook_storage.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/cluster-config.yaml.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/compatibility-translation.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/config-shape.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/defaults/00-bootstrap.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/defaults/10-env.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/defaults/20-tls-files.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/defaults/30-base-config.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/defaults/40-resources.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/defaults/50-images.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/defaults/70-scanner-v4.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/defaults/70-scanner.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/defaults/whats-this.md create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/expandables.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/scanner-config-shape.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/internal/scanner-v4-config-shape.yaml create mode 100755 rhacs/4.5.2/secured-cluster-services/scripts/fetch-secrets.sh create mode 100644 rhacs/4.5.2/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/sensor-chart-upgrade.md create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/00-injected-ca-bundle.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/00-main-image-pull-secrets.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/00-storage-class.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-01-psps.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-01-security.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-05-network-policy.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-06-deployment.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-07-service.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-08-hpa.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-00-serviceaccount.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-psps.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-security.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-02-db-password-secret.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-db-config.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-indexer-config.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-db-network-policy.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-indexer-network-policy.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-06-db-pvc.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-db-deployment.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-indexer-deployment.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-db-service.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-indexer-service.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-09-indexer-hpa.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/99-shared-openshift-monitoring.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/NOTES.txt create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_compatibility.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_crypto.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_defaults.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_dict.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_expand.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_format.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_helpers.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_image-pull-secrets.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_images.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_init.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_injected-ca-bundle.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_labels.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_lookup.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_metadata.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_openshift.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_psp.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_pvcs.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_reporting.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_scanner-v4_init.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_scanner-v4_volume.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_scanner_init.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_set_install_method.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/_storage_classes.tpl create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/additional-ca-sensor.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/admission-controller-netpol.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/admission-controller-pod-security.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/admission-controller-rbac.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/admission-controller-secret.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/admission-controller.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/cluster-config.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/collector-netpol.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/collector-pod-security.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/collector-rbac.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/collector-scc.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/collector-secret.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/collector.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/openshift-monitoring.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/sensor-compliance-rbac.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/sensor-netpol.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/sensor-pod-security.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/sensor-rbac.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/sensor-secret.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/sensor.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/service-ca.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/templates/upgrader-serviceaccount.yaml create mode 100644 rhacs/4.5.2/secured-cluster-services/values-private-scanner-v4.yaml.example create mode 100644 rhacs/4.5.2/secured-cluster-services/values-private.yaml.example create mode 100644 rhacs/4.5.2/secured-cluster-services/values-public-scanner-v4.yaml.example create mode 100644 rhacs/4.5.2/secured-cluster-services/values-public.yaml.example create mode 100644 rhacs/4.5.2/secured-cluster-services/values-scanner.yaml.example create mode 100644 rhacs/4.5.2/secured-cluster-services/values.yaml diff --git a/4.5.2/central-services/.helmignore b/4.5.2/central-services/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/4.5.2/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.5.2/central-services/Chart.yaml b/4.5.2/central-services/Chart.yaml new file mode 100644 index 0000000..7ac9407 --- /dev/null +++ b/4.5.2/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/StackRox_icon.png +description: Helm Chart for StackRox Central Service +type: application +version: 400.5.2 +appVersion: 4.5.2 diff --git a/4.5.2/central-services/README.md b/4.5.2/central-services/README.md new file mode 100644 index 0000000..a39ab2e --- /dev/null +++ b/4.5.2/central-services/README.md @@ -0,0 +1,221 @@ +# 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://raw.githubusercontent.com/stackrox/helm-charts/main/opensource/. +To use StackRox Helm charts on your machine, run +```sh +helm repo add stackrox https://raw.githubusercontent.com/stackrox/helm-charts/main/opensource/ +``` +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 + + scannerV4: + # Enable Scanner V4, which will become the default scanner for StackRox. + # Note that enabling Scanner V4 while having the StackRox Scanner disabled (scanner.disable=true) + # is not a supported configuration. + disable: false + + 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. + +Alternatively, you can also use the `--reuse-values` for the `helm upgrade` command. This flag +causes values which were previously passed via `--values / -f`, `--set` or `--set-file` to be +automatically passed again to the Helm chart rendering. + +### Passing Generated Values + +The Helm chart can conveniently automatically generate certain sensitive data objects. This includes +passwords, keys and certificates. If these data objects were generated during the installation +of the Helm chart, a command is provided as part of the post-installation notes which can be used +for retrieving them and storing them in a file `generated-values.yaml`. This file +might contain a CA key. + +If, during an upgrade of the Helm release, the Helm chart needs to generate a new certificate for +some component, it is required to pass in the existing CA, for example by adding +`-f generated-values.yaml` to the arguments for `helm upgrade`. + +### Enabling Scanner V4 + +Beginning with StackRox 4.4, a new scanner component based on ClairCore named Scanner V4 is integrated. +In a future version of StackRox, Scanner V4 will become the new default scanner and replace the existing +scanner named StackRox Scanner. Currently, Scanner V4 is not installed by default, but it +can be enabled alongside StackRox Scanner using the following Helm chart setting: + +``` +scannerV4: + disable: false +``` + +To enable Scanner V4 for an existing installation of this chart, the CA certificate +and its key must be provided to the `helm upgrade` command. +For example, if the CA was generated ahead of time and injected into the `helm install` command, then +the `--reuse-values` flag for `helm upgrade` can be used to provide the certificate and key. However, if the CA was +generated by the Helm chart at installation time, you must retrieve the generated secret +values from the cluster (see above) and provide those to the `helm upgrade` command. + +Note that because Scanner V4 currently runs simultaneously with StackRox Scanner, your +cluster must have sufficient computing resources available to host both scanner components at the same time. +The default resource configuration for Scanner V4 components can be found in the file +internal/defaults.yaml. diff --git a/4.5.2/central-services/assets/Red_Hat-Hat_icon.png b/4.5.2/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.5.2/central-services/assets/StackRox_icon.png b/4.5.2/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.5.2/central-services/config-templates/scanner-v4-db/pg_hba.conf.default b/4.5.2/central-services/config-templates/scanner-v4-db/pg_hba.conf.default new file mode 100644 index 0000000..650f2fe --- /dev/null +++ b/4.5.2/central-services/config-templates/scanner-v4-db/pg_hba.conf.default @@ -0,0 +1,23 @@ +# 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 reject +host replication all 127.0.0.1/32 reject +host replication all ::1/128 reject + +### 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.5.2/central-services/config-templates/scanner-v4-db/postgresql.conf.default b/4.5.2/central-services/config-templates/scanner-v4-db/postgresql.conf.default new file mode 100644 index 0000000..63ed892 --- /dev/null +++ b/4.5.2/central-services/config-templates/scanner-v4-db/postgresql.conf.default @@ -0,0 +1,75 @@ +#------------------------------------------------------------------------------ +# FILE LOCATIONS +#------------------------------------------------------------------------------ + +hba_file = '/etc/stackrox.d/config/pg_hba.conf' + +#------------------------------------------------------------------------------ +# CONNECTIONS AND AUTHENTICATION +#------------------------------------------------------------------------------ + +# - Connection Settings - + +listen_addresses = '*' +max_connections = 500 + +# - Authentication - + +password_encryption = 'scram-sha-256' + +# - SSL - + +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' + +#------------------------------------------------------------------------------ +# RESOURCE USAGE (except WAL) +#------------------------------------------------------------------------------ + +# - Memory - + +# Keep this in sync with the shared-memory volume in the +# templates/02-scanner-v4-07-db-deployment.yaml +shared_buffers = 750MB +work_mem = 16MB +maintenance_work_mem = 128MB +dynamic_shared_memory_type = posix + +#------------------------------------------------------------------------------ +# WRITE-AHEAD LOG +#------------------------------------------------------------------------------ + +# - Checkpoints - + +max_wal_size = 3GB +min_wal_size = 80MB + +#------------------------------------------------------------------------------ +# REPORTING AND LOGGING +#------------------------------------------------------------------------------ + +# - What to Log - + +log_timezone = 'Etc/UTC' + +#------------------------------------------------------------------------------ +# CLIENT CONNECTION DEFAULTS +#------------------------------------------------------------------------------ + +# - Locale and Formatting - + +datestyle = 'iso, mdy' +timezone = 'Etc/UTC' + +lc_messages = 'en_US.utf8' +lc_monetary = 'en_US.utf8' +lc_numeric = 'en_US.utf8' +lc_time = 'en_US.utf8' + +default_text_search_config = 'pg_catalog.english' + +# - Shared Library Preloading - + +shared_preload_libraries = 'pg_stat_statements' diff --git a/4.5.2/central-services/config-templates/scanner-v4/indexer-config.yaml.tpl b/4.5.2/central-services/config-templates/scanner-v4/indexer-config.yaml.tpl new file mode 100644 index 0000000..c5d28fc --- /dev/null +++ b/4.5.2/central-services/config-templates/scanner-v4/indexer-config.yaml.tpl @@ -0,0 +1,47 @@ +{{- /* + This is the configuration file template for the Scanner v4 Indexer. + 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 v4 Indexer. +stackrox_services: true +indexer: + enable: true + database: + conn_string: > + host=scanner-v4-db.{{ .Release.Namespace }}.svc + port=5432 + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + user=postgres + sslmode=verify-full +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.statementTimeoutMs) }} + statement_timeout={{._rox.scannerV4.db.source.statementTimeoutMs}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.minConns) }} + pool_min_conns={{._rox.scannerV4.db.source.minConns}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.maxConns) }} + pool_max_conns={{._rox.scannerV4.db.source.maxConns}} +{{- end }} + client_encoding=UTF8 + password_file: /run/secrets/stackrox.io/secrets/password + get_layer_timeout: 1m + {{- if ._rox.env.centralServices }} + repository_to_cpe_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?file=repo2cpe + name_to_repos_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?file=name2repos + {{- else }} + repository_to_cpe_url: https://sensor.{{ .Release.Namespace }}.svc/scanner/definitions?file=repo2cpe + name_to_repos_url: https://sensor.{{ .Release.Namespace }}.svc/scanner/definitions?file=name2repos + {{- end }} + repository_to_cpe_file: /run/mappings/repository-to-cpe.json + name_to_repos_file: /run/mappings/container-name-repos-map.json +matcher: + enable: false +log_level: "{{ ._rox.scannerV4.indexer.logLevel }}" +grpc_listen_addr: 0.0.0.0:8443 +http_listen_addr: 0.0.0.0:9443 +proxy: + config_dir: /run/secrets/stackrox.io/proxy-config + config_file: config.yaml diff --git a/4.5.2/central-services/config-templates/scanner-v4/matcher-config.yaml.tpl b/4.5.2/central-services/config-templates/scanner-v4/matcher-config.yaml.tpl new file mode 100644 index 0000000..4414553 --- /dev/null +++ b/4.5.2/central-services/config-templates/scanner-v4/matcher-config.yaml.tpl @@ -0,0 +1,39 @@ +{{- /* + This is the configuration file template for the Scanner v4 Matcher. + 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 v4 Matcher. +stackrox_services: true +indexer: + enable: false +matcher: + enable: true + database: + conn_string: > + host=scanner-v4-db.{{ .Release.Namespace }}.svc + port=5432 + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + user=postgres + sslmode=verify-full +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.statementTimeoutMs) }} + statement_timeout={{._rox.scannerV4.db.source.statementTimeoutMs}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.minConns) }} + pool_min_conns={{._rox.scannerV4.db.source.minConns}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.maxConns) }} + pool_max_conns={{._rox.scannerV4.db.source.maxConns}} +{{- end }} + client_encoding=UTF8 + password_file: /run/secrets/stackrox.io/secrets/password + vulnerabilities_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?version=ROX_VERSION + indexer_addr: scanner-v4-indexer.{{ .Release.Namespace }}.svc:8443 +log_level: "{{ ._rox.scannerV4.matcher.logLevel }}" +grpc_listen_addr: 0.0.0.0:8443 +http_listen_addr: 0.0.0.0:9443 +proxy: + config_dir: /run/secrets/stackrox.io/proxy-config + config_file: config.yaml diff --git a/4.5.2/central-services/config-templates/scanner/config.yaml.tpl b/4.5.2/central-services/config-templates/scanner/config.yaml.tpl new file mode 100644 index 0000000..5efc0b9 --- /dev/null +++ b/4.5.2/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.5.2/central-services/config/central/config.yaml.default b/4.5.2/central-services/config/central/config.yaml.default new file mode 100644 index 0000000..d85c852 --- /dev/null +++ b/4.5.2/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.5.2/central-services/config/central/endpoints.yaml.default b/4.5.2/central-services/config/central/endpoints.yaml.default new file mode 100644 index 0000000..25549d6 --- /dev/null +++ b/4.5.2/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.5.2/central-services/config/centraldb/pg_hba.conf.default b/4.5.2/central-services/config/centraldb/pg_hba.conf.default new file mode 100644 index 0000000..8229f95 --- /dev/null +++ b/4.5.2/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.5.2/central-services/config/centraldb/postgresql.conf.default b/4.5.2/central-services/config/centraldb/postgresql.conf.default new file mode 100644 index 0000000..057e7ea --- /dev/null +++ b/4.5.2/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.5.2/central-services/config/proxy-config.yaml.default b/4.5.2/central-services/config/proxy-config.yaml.default new file mode 100644 index 0000000..73df050 --- /dev/null +++ b/4.5.2/central-services/config/proxy-config.yaml.default @@ -0,0 +1,27 @@ +# # NOTE: Central, Scanner, Scanner v4 Indexer, and Scanner v4 Matcher 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 +# # - $KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT +# 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.5.2/central-services/internal/annotations/helm-hook_secret.yaml b/4.5.2/central-services/internal/annotations/helm-hook_secret.yaml new file mode 100644 index 0000000..68eea0c --- /dev/null +++ b/4.5.2/central-services/internal/annotations/helm-hook_secret.yaml @@ -0,0 +1,2 @@ +helm.sh/hook: pre-install,pre-upgrade +helm.sh/resource-policy: keep diff --git a/4.5.2/central-services/internal/annotations/helm-hook_storage.yaml b/4.5.2/central-services/internal/annotations/helm-hook_storage.yaml new file mode 100644 index 0000000..7376533 --- /dev/null +++ b/4.5.2/central-services/internal/annotations/helm-hook_storage.yaml @@ -0,0 +1,3 @@ +helm.sh/hook: pre-install,pre-upgrade +helm.sh/resource-policy: keep +helm.sh/hook-delete-policy: never diff --git a/4.5.2/central-services/internal/bootstrap-defaults.yaml.tpl b/4.5.2/central-services/internal/bootstrap-defaults.yaml.tpl new file mode 100644 index 0000000..8f8e559 --- /dev/null +++ b/4.5.2/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.5.2/central-services/internal/config-shape.yaml b/4.5.2/central-services/internal/config-shape.yaml new file mode 100644 index 0000000..96a2d8a --- /dev/null +++ b/4.5.2/central-services/internal/config-shape.yaml @@ -0,0 +1,192 @@ +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 + storageClasses: + all: {} # dict + default: null # string + pvcs: + names: null # [string] +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] + hostAliases: null # [dict] + affinity: null # dict + priorityClassName: null # string + 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] + hostAliases: null # [dict] + priorityClassName: null # string + 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 + scanner-v4-indexer: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner-v4-matcher: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner-v4-db: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + other: {} # dict +allowNonstandardNamespace: null # bool +allowNonstandardReleaseName: null # bool +allowUnsupportedHelmVersion: 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 +network: + enableNetworkPolicies: null # bool +system: + enablePodSecurityPolicies: null # bool diff --git a/4.5.2/central-services/internal/defaults.yaml b/4.5.2/central-services/internal/defaults.yaml new file mode 100644 index 0000000..4c55f1a --- /dev/null +++ b/4.5.2/central-services/internal/defaults.yaml @@ -0,0 +1,331 @@ +defaults: + + imagePullSecrets: + allowNone: true + useExisting: [] + useFromDefaultServiceAccount: true + + image: + registry: quay.io/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.5.2 + + 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.5.2 + + 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.5.2 + + dbResources: + limits: + cpu: "2000m" + memory: "4Gi" + requests: + cpu: "200m" + memory: "512Mi" + + dbImage: + name: scanner-db + tag: 4.5.2 + scannerV4: + disable: true + image: + name: scanner-v4 + tag: 4.5.2 + indexer: + disable: false + logLevel: INFO + metricsPort: 9090 + replicas: 3 + autoscaling: + minReplicas: 2 + maxReplicas: 5 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: + app: scanner-v4-indexer + 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: "3Gi" + cpu: "2000m" + matcher: + logLevel: INFO + metricsPort: 9090 + replicas: 2 + autoscaling: + minReplicas: 2 + maxReplicas: 3 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: + app: scanner-v4-matcher + 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: "500Mi" + cpu: "1000m" + limits: + memory: "2Gi" + cpu: "2000m" + db: + postgresConfig: "@config-templates/scanner-v4-db/postgresql.conf|config-templates/scanner-v4-db/postgresql.conf.default" + hbaConfig: "@config-templates/scanner-v4-db/pg_hba.conf|config-templates/scanner-v4-db/pg_hba.conf.default" + source: + minConns: 5 + maxConns: 40 + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Scanner V4 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 + resources: + requests: + cpu: "200m" + memory: "3Gi" + limits: + cpu: "2000m" + memory: "4Gi" + image: + name: scanner-v4-db + tag: 4.5.2 + exposeMonitoring: false + + network: + enableNetworkPolicies: true + + system: + +pvcDefaults: + claimName: "stackrox-db" + size: "100Gi" + +dbPVCDefaults: + claimName: "central-db" + size: "100Gi" +scannerV4DBPVCDefaults: + claimName: "scanner-v4-db" + size: "50Gi" + createClaim: true diff --git a/4.5.2/central-services/internal/expandables.yaml b/4.5.2/central-services/internal/expandables.yaml new file mode 100644 index 0000000..5054a52 --- /dev/null +++ b/4.5.2/central-services/internal/expandables.yaml @@ -0,0 +1,71 @@ +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 +scannerV4: + indexer: + nodeSelector: true + resources: true + serviceTLS: + cert: true + key: true + matcher: + nodeSelector: true + resources: true + serviceTLS: + cert: true + key: true + db: + nodeSelector: true + resources: true + postgresConfig: true + hbaConfig: true + password: + value: true + serviceTLS: + cert: true + key: true diff --git a/4.5.2/central-services/internal/platforms/default.yaml b/4.5.2/central-services/internal/platforms/default.yaml new file mode 100644 index 0000000..180f5c8 --- /dev/null +++ b/4.5.2/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.5.2/central-services/internal/platforms/gke.yaml b/4.5.2/central-services/internal/platforms/gke.yaml new file mode 100644 index 0000000..70d7b32 --- /dev/null +++ b/4.5.2/central-services/internal/platforms/gke.yaml @@ -0,0 +1,2 @@ +pvcDefaults: + storageClass: "stackrox-gke-ssd" diff --git a/4.5.2/central-services/internal/scanner-config-shape.yaml b/4.5.2/central-services/internal/scanner-config-shape.yaml new file mode 100644 index 0000000..1a5d26f --- /dev/null +++ b/4.5.2/central-services/internal/scanner-config-shape.yaml @@ -0,0 +1,44 @@ +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] + hostAliases: null # [dict] + dbHostAliases: null # [dict] + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + affinity: null # dict + priorityClassName: null # string + dbPriorityClassName: null # string + 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.5.2/central-services/internal/scanner-v4-config-shape.yaml b/4.5.2/central-services/internal/scanner-v4-config-shape.yaml new file mode 100644 index 0000000..a705b53 --- /dev/null +++ b/4.5.2/central-services/internal/scanner-v4-config-shape.yaml @@ -0,0 +1,79 @@ +scannerV4: + disable: null # bool + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + indexer: + disable: null # bool + metricsPort: null # int + logLevel: null # string + replicas: null # int + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + matcher: + metricsPort: null # int + logLevel: null # string + replicas: null # int + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + db: + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + source: + minConns: null # int + maxConns: null # int + statementTimeoutMs: null # int + configOverride: null # string + password: + value: null # string + generate: null # bool + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + postgresConfig: null # string + hbaConfig: null # string + 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] + exposeMonitoring: null # bool diff --git a/4.5.2/central-services/templates/00-additional-ca.yaml b/4.5.2/central-services/templates/00-additional-ca.yaml new file mode 100644 index 0000000..67b0c2b --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/00-image-pull-secret.yaml b/4.5.2/central-services/templates/00-image-pull-secret.yaml new file mode 100644 index 0000000..1fc3e34 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/00-injected-ca-bundle.yaml b/4.5.2/central-services/templates/00-injected-ca-bundle.yaml new file mode 100644 index 0000000..3289c2a --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/00-proxy-config-secret.yaml b/4.5.2/central-services/templates/00-proxy-config-secret.yaml new file mode 100644 index 0000000..c357179 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/00-stackrox-application.yaml b/4.5.2/central-services/templates/00-stackrox-application.yaml new file mode 100644 index 0000000..5d320f8 --- /dev/null +++ b/4.5.2/central-services/templates/00-stackrox-application.yaml @@ -0,0 +1,124 @@ +{{- 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 +{{- if ._rox.network.enableNetworkPolicies }} + - group: networking.k8s.io + kind: NetworkPolicy +{{- end }} + - 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.5.2/central-services/templates/00-storage-class.yaml b/4.5.2/central-services/templates/00-storage-class.yaml new file mode 100644 index 0000000..ed5c3a0 --- /dev/null +++ b/4.5.2/central-services/templates/00-storage-class.yaml @@ -0,0 +1,26 @@ +{{- include "srox.init" . -}} + + +{{- $name := "stackrox-gke-ssd" -}} +{{- if has $name ._rox._state.referencedStorageClasses }} + {{- $lookupOut := dict -}} + {{- $globalName := include "srox.globalResourceName" (list . $name) -}} + {{- $_ := include "srox.safeLookup" (list . $lookupOut "storage.k8s.io/v1" "StorageClass" "" $globalName) -}} + {{- if and (not $lookupOut.result) (or .Release.IsInstall $lookupOut.reliable) (not ._rox.meta.noCreateStorageClass) }} + +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ $globalName }} + labels: + {{- include "srox.labels" (list . "storageclass" $name) | nindent 4 }} + annotations: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "storageclass" $name $annotations) | nindent 4 }} +provisioner: kubernetes.io/gce-pd +parameters: + type: pd-ssd + + {{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/01-central-00-db-serviceaccount.yaml b/4.5.2/central-services/templates/01-central-00-db-serviceaccount.yaml new file mode 100644 index 0000000..e48883a --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-00-serviceaccount.yaml b/4.5.2/central-services/templates/01-central-00-serviceaccount.yaml new file mode 100644 index 0000000..8c257f6 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-01-license-secret.yaml b/4.5.2/central-services/templates/01-central-01-license-secret.yaml new file mode 100644 index 0000000..0d26dda --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-02-db-psps.yaml b/4.5.2/central-services/templates/01-central-02-db-psps.yaml new file mode 100644 index 0000000..870dd40 --- /dev/null +++ b/4.5.2/central-services/templates/01-central-02-db-psps.yaml @@ -0,0 +1,80 @@ +{{- 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.db.persistence.hostPath }} + allowedHostPaths: + - pathPrefix: {{._rox.central.db.persistence.hostPath}} + {{- 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.5.2/central-services/templates/01-central-02-db-security.yaml b/4.5.2/central-services/templates/01-central-02-db-security.yaml new file mode 100644 index 0000000..6017d09 --- /dev/null +++ b/4.5.2/central-services/templates/01-central-02-db-security.yaml @@ -0,0 +1,44 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.env.openshift }} +--- +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: + - nonroot-v2 + {{- if ._rox.central.db.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.5.2/central-services/templates/01-central-02-psps.yaml b/4.5.2/central-services/templates/01-central-02-psps.yaml new file mode 100644 index 0000000..1ba51f5 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-02-security.yaml b/4.5.2/central-services/templates/01-central-02-security.yaml new file mode 100644 index 0000000..4976d63 --- /dev/null +++ b/4.5.2/central-services/templates/01-central-02-security.yaml @@ -0,0 +1,44 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.env.openshift }} +--- +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: + - nonroot-v2 + {{- 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.5.2/central-services/templates/01-central-03-cloud-credentials-rbac.yaml b/4.5.2/central-services/templates/01-central-03-cloud-credentials-rbac.yaml new file mode 100644 index 0000000..e9bb421 --- /dev/null +++ b/4.5.2/central-services/templates/01-central-03-cloud-credentials-rbac.yaml @@ -0,0 +1,34 @@ +{{- include "srox.init" . -}} + +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: central-sts-config-reader + namespace: {{ .Release.Namespace }} + annotations: + {{- include "srox.annotations" (list . "role" "central-sts-config-reader") | nindent 4 }} + labels: + {{- include "srox.labels" (list . "role" "central-sts-config-reader") | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["secrets"] + resourceNames: ["gcp-cloud-credentials"] + verbs: ["get", "list", "watch"] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: central-sts-config-reader + namespace: {{ .Release.Namespace }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "central-sts-config-reader") | nindent 4 }} + labels: + {{- include "srox.labels" (list . "rolebinding" "central-sts-config-reader") | nindent 4 }} +subjects: + - kind: ServiceAccount + name: central + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: central-sts-config-reader + apiGroup: rbac.authorization.k8s.io diff --git a/4.5.2/central-services/templates/01-central-03-diagnostics-rbac.yaml b/4.5.2/central-services/templates/01-central-03-diagnostics-rbac.yaml new file mode 100644 index 0000000..4c83007 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-04-htpasswd-secret.yaml b/4.5.2/central-services/templates/01-central-04-htpasswd-secret.yaml new file mode 100644 index 0000000..59b338e --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-05-db-tls-secret.yaml b/4.5.2/central-services/templates/01-central-05-db-tls-secret.yaml new file mode 100644 index 0000000..3a3a1fa --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-05-tls-secret.yaml b/4.5.2/central-services/templates/01-central-05-tls-secret.yaml new file mode 100644 index 0000000..1850d46 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-06-default-tls-cert-secret.yaml b/4.5.2/central-services/templates/01-central-06-default-tls-cert-secret.yaml new file mode 100644 index 0000000..010444c --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-08-configmap.yaml b/4.5.2/central-services/templates/01-central-08-configmap.yaml new file mode 100644 index 0000000..9420e59 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-08-db-configmap.yaml b/4.5.2/central-services/templates/01-central-08-db-configmap.yaml new file mode 100644 index 0000000..0a0a2c7 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-08-external-db-configmap.yaml b/4.5.2/central-services/templates/01-central-08-external-db-configmap.yaml new file mode 100644 index 0000000..48d2427 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-09-endpoints-config.yaml b/4.5.2/central-services/templates/01-central-09-endpoints-config.yaml new file mode 100644 index 0000000..fa6204e --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-10-db-networkpolicy.yaml b/4.5.2/central-services/templates/01-central-10-db-networkpolicy.yaml new file mode 100644 index 0000000..b33460d --- /dev/null +++ b/4.5.2/central-services/templates/01-central-10-db-networkpolicy.yaml @@ -0,0 +1,28 @@ +{{- include "srox.init" . -}} + +{{ if and ._rox.network.enableNetworkPolicies (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.5.2/central-services/templates/01-central-10-networkpolicy.yaml b/4.5.2/central-services/templates/01-central-10-networkpolicy.yaml new file mode 100644 index 0000000..dcd5e03 --- /dev/null +++ b/4.5.2/central-services/templates/01-central-10-networkpolicy.yaml @@ -0,0 +1,67 @@ +{{- include "srox.init" . -}} + +{{ if ._rox.network.enableNetworkPolicies }} +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 }} +{{- end }} diff --git a/4.5.2/central-services/templates/01-central-11-db-pvc.yaml b/4.5.2/central-services/templates/01-central-11-db-pvc.yaml new file mode 100644 index 0000000..72763bf --- /dev/null +++ b/4.5.2/central-services/templates/01-central-11-db-pvc.yaml @@ -0,0 +1,64 @@ +{{- 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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "persistentvolume" $pvName $annotations) | nindent 4 }} +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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "persistentvolumeclaim" $claimName $annotations) | nindent 4 }} +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/01-central-11-pvc.yaml b/4.5.2/central-services/templates/01-central-11-pvc.yaml new file mode 100644 index 0000000..2ec1916 --- /dev/null +++ b/4.5.2/central-services/templates/01-central-11-pvc.yaml @@ -0,0 +1,61 @@ +{{- 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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "persistentvolume" $pvName $annotations) | nindent 4 }} +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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "persistentvolumeclaim" $claimName $annotations) | nindent 4 }} +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} diff --git a/4.5.2/central-services/templates/01-central-12-central-db.yaml b/4.5.2/central-services/templates/01-central-12-central-db.yaml new file mode 100644 index 0000000..cab6600 --- /dev/null +++ b/4.5.2/central-services/templates/01-central-12-central-db.yaml @@ -0,0 +1,206 @@ +{{- 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: + {{- $annotations := dict -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "nonroot-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "central-db" $annotations) | nindent 8 }} + spec: + {{- if ._rox.central.db._nodeSelector }} + nodeSelector: + {{- ._rox.central.db._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.central.db.hostAliases }} + hostAliases: {{ toYaml ._rox.central.db.hostAliases | 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 + {{- if ._rox.central.db.priorityClassName }} + priorityClassName: {{ ._rox.central.db.priorityClassName }} + {{- end }} + 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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_secret" $annotations) -}} + {{- include "srox.annotations" (list . "secret" "central-db-password" $annotations) | nindent 4 }} +type: Opaque +stringData: + password: | + {{- ._rox.central.db._password.value | nindent 4 }} +{{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/01-central-13-deployment.yaml b/4.5.2/central-services/templates/01-central-13-deployment.yaml new file mode 100644 index 0000000..8bb04ec --- /dev/null +++ b/4.5.2/central-services/templates/01-central-13-deployment.yaml @@ -0,0 +1,308 @@ +{{- 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + 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 }} + {{- if ._rox.central.priorityClassName }} + priorityClassName: {{ ._rox.central.priorityClassName }} + {{- end }} + {{- if ._rox.central.hostAliases }} + hostAliases: {{ toYaml ._rox.central.hostAliases | nindent 8 }} + {{- end }} + 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: ROX_MEMLIMIT + 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 telemetry.enabled is true or null, configure the endpoint and + the key, if provided. Also, configure additional listening endpoints.*/}} + {{- 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 }} + - name: ROX_TELEMETRY_API_WHITELIST + value: "/api/splunk/ta/*,/v1/auth/m2m/exchange,/api/cli/download/*" + {{- /* Otherwise... */}} + {{- else }} + {{- /* ... if telemetry.enabled is false, configure the key to disable + telemetry collection */}} + - name: ROX_TELEMETRY_STORAGE_KEY_V1 + value: "DISABLED" + {{- 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 }} + {{- if ._rox._scannerV4Enabled }} + - name: ROX_SCANNER_V4 + value: "true" + {{- end }} + {{- 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.env.openshift }} + - name: central-bound-sa-token + mountPath: /var/run/secrets/openshift/serviceaccount + readOnly: true + {{- end }} + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: central-encryption-key-chain + mountPath: /run/secrets/stackrox.io/central-encryption-key-chain + {{- 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.env.openshift }} + - name: central-bound-sa-token + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + path: token + audience: openshift + expirationSeconds: 3600 + {{- end }} + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: central-encryption-key-chain + secret: + secretName: central-encryption-key-chain + {{- 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 + {{- 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.5.2/central-services/templates/01-central-14-service.yaml b/4.5.2/central-services/templates/01-central-14-service.yaml new file mode 100644 index 0000000..f459fd7 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/01-central-15-exposure.yaml b/4.5.2/central-services/templates/01-central-15-exposure.yaml new file mode 100644 index 0000000..9bfdbbb --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/02-scanner-00-serviceaccount.yaml b/4.5.2/central-services/templates/02-scanner-00-serviceaccount.yaml new file mode 100644 index 0000000..a27c602 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/02-scanner-01-psps.yaml b/4.5.2/central-services/templates/02-scanner-01-psps.yaml new file mode 100644 index 0000000..23b398c --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/02-scanner-01-security.yaml b/4.5.2/central-services/templates/02-scanner-01-security.yaml new file mode 100644 index 0000000..05ff6f1 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-01-security.yaml @@ -0,0 +1,45 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable }} + +{{- if ._rox.env.openshift }} +--- +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: + - nonroot-v2 + 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.5.2/central-services/templates/02-scanner-02-db-password-secret.yaml b/4.5.2/central-services/templates/02-scanner-02-db-password-secret.yaml new file mode 100644 index 0000000..c6c0bc1 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/02-scanner-03-tls-secret.yaml b/4.5.2/central-services/templates/02-scanner-03-tls-secret.yaml new file mode 100644 index 0000000..7c590ff --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/02-scanner-04-scanner-config.yaml b/4.5.2/central-services/templates/02-scanner-04-scanner-config.yaml new file mode 100644 index 0000000..4ed16c7 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/02-scanner-05-network-policy.yaml b/4.5.2/central-services/templates/02-scanner-05-network-policy.yaml new file mode 100644 index 0000000..a61b59e --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-05-network-policy.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies -}} +{{- 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 + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP + 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 }} +{{ end }} diff --git a/4.5.2/central-services/templates/02-scanner-06-deployment.yaml b/4.5.2/central-services/templates/02-scanner-06-deployment.yaml new file mode 100644 index 0000000..6bbe53c --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-06-deployment.yaml @@ -0,0 +1,318 @@ +{{- 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scanner._nodeSelector }} + nodeSelector: + {{- ._rox.scanner._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.tolerations }} + tolerations: + {{- toYaml ._rox.scanner.tolerations | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.hostAliases }} + hostAliases: {{ toYaml ._rox.scanner.hostAliases | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scanner.affinity | nindent 8 }} + {{- if ._rox.scanner.priorityClassName }} + priorityClassName: {{ ._rox.scanner.priorityClassName }} + {{- end }} + 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: ROX_MEMLIMIT + 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 + {{- if eq ._rox.scanner.mode "slim" }} + secretName: additional-ca-sensor + {{- else }} + secretName: additional-ca + {{- end }} + - 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scanner._dbNodeSelector }} + nodeSelector: + {{- ._rox.scanner._dbNodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.dbHostAliases }} + hostAliases: {{ toYaml ._rox.scanner.dbHostAliases | 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 + {{- if ._rox.scanner.dbPriorityClassName }} + priorityClassName: {{ ._rox.scanner.dbPriorityClassName }} + {{- end }} + 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.5.2/central-services/templates/02-scanner-07-service.yaml b/4.5.2/central-services/templates/02-scanner-07-service.yaml new file mode 100644 index 0000000..2f65b15 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/02-scanner-08-hpa.yaml b/4.5.2/central-services/templates/02-scanner-08-hpa.yaml new file mode 100644 index 0000000..c7af476 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/02-scanner-v4-00-serviceaccount.yaml b/4.5.2/central-services/templates/02-scanner-v4-00-serviceaccount.yaml new file mode 100644 index 0000000..91e4c8e --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-00-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} +{{- if (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: scanner-v4 + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "scanner-v4") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "scanner-v4") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-01-psps.yaml b/4.5.2/central-services/templates/02-scanner-v4-01-psps.yaml new file mode 100644 index 0000000..14e38b4 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-01-psps.yaml @@ -0,0 +1,72 @@ +{{- include "srox.init" . -}} +{{- if and (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-scanner-v4-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-scanner-v4-psp") | nindent 4 }} +rules: +- apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4") }} + verbs: + - use + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-scanner-v4-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-scanner-v4-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-scanner-v4-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4-psp") }} +subjects: +- kind: ServiceAccount + name: scanner-v4 + namespace: {{ .Release.Namespace }} + +--- + +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-scanner-v4") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-scanner-v4") | 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.5.2/central-services/templates/02-scanner-v4-01-security.yaml b/4.5.2/central-services/templates/02-scanner-v4-01-security.yaml new file mode 100644 index 0000000..d76329c --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-01-security.yaml @@ -0,0 +1,51 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled }} + {{- if ._rox.env.openshift }} + {{- if eq ._rox.env.openshift 3 }} + {{ include "srox.warn" (list . "On OpenShift 3.x no SecurityContextConstraint will be configured for Scanner V4.") }} + {{- else }} + {{/* Use a default SCC that ships with OpenShift 4.x. + We only need to create a Role and a RoleBinding for + associating the SCC with the Scanner V4 deployment. */}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-scanner-v4-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-scanner-v4-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-scanner-v4-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - nonroot-v2 + verbs: + - use + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: scanner-v4-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "scanner-v4-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "scanner-v4-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-scanner-v4-scc +subjects: +- kind: ServiceAccount + name: scanner-v4 + namespace: {{ .Release.Namespace }} + {{- end }} + {{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-02-db-password-secret.yaml b/4.5.2/central-services/templates/02-scanner-v4-02-db-password-secret.yaml new file mode 100644 index 0000000..a382d3e --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-02-db-password-secret.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} +{{- /* The (...) below safe-guard against nil pointer evaluations for Helm versions built with Go < 1.18. */}} +{{- if and ._rox.scannerV4._dbEnabled (not (kindIs "invalid" (._rox.scannerV4.db._password).value)) }} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.scannerV4.db._password.value | nindent 4 }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-03-db-tls-secret.yaml b/4.5.2/central-services/templates/02-scanner-v4-03-db-tls-secret.yaml new file mode 100644 index 0000000..769f852 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-03-db-tls-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._dbEnabled ._rox.scannerV4.db._serviceTLS ._rox._ca }} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-db-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-db-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-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.scannerV4.db._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scannerV4.db._serviceTLS.Key | nindent 4 }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-03-indexer-tls-secret.yaml b/4.5.2/central-services/templates/02-scanner-v4-03-indexer-tls-secret.yaml new file mode 100644 index 0000000..c0e2a92 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-03-indexer-tls-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled ._rox.scannerV4.indexer._serviceTLS ._rox._ca }} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-indexer-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-indexer-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-indexer-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.scannerV4.indexer._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scannerV4.indexer._serviceTLS.Key | nindent 4 }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-03-matcher-tls-secret.yaml b/4.5.2/central-services/templates/02-scanner-v4-03-matcher-tls-secret.yaml new file mode 100644 index 0000000..cdc4d9f --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-03-matcher-tls-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._matcherEnabled ._rox.scannerV4.matcher._serviceTLS ._rox._ca -}} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-matcher-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-matcher-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-matcher-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.scannerV4.matcher._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scannerV4.matcher._serviceTLS.Key | nindent 4 }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-04-db-config.yaml b/4.5.2/central-services/templates/02-scanner-v4-04-db-config.yaml new file mode 100644 index 0000000..439cfe8 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-04-db-config.yaml @@ -0,0 +1,17 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-db-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-db-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-db-config") | nindent 4 }} +data: + postgresql.conf: | + {{- ._rox.scannerV4.db._postgresConfig | nindent 4 }} + pg_hba.conf: | + {{- ._rox.scannerV4.db._hbaConfig | nindent 4 }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-04-indexer-config.yaml b/4.5.2/central-services/templates/02-scanner-v4-04-indexer-config.yaml new file mode 100644 index 0000000..26705b8 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-04-indexer-config.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-indexer-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-indexer-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-indexer-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner-v4/indexer-config.yaml.tpl") . | nindent 4 }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-04-matcher-config.yaml b/4.5.2/central-services/templates/02-scanner-v4-04-matcher-config.yaml new file mode 100644 index 0000000..6704367 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-04-matcher-config.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._matcherEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-matcher-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-matcher-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-matcher-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner-v4/matcher-config.yaml.tpl") . | nindent 4 }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-05-db-network-policy.yaml b/4.5.2/central-services/templates/02-scanner-v4-05-db-network-policy.yaml new file mode 100644 index 0000000..875aba8 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-05-db-network-policy.yaml @@ -0,0 +1,39 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-db") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-db + ingress: +{{- if ._rox.scannerV4._indexerEnabled }} + - from: + - podSelector: + matchLabels: + app: scanner-v4-indexer + ports: + - port: 5432 + protocol: TCP +{{- end }} +{{- if ._rox.scannerV4._matcherEnabled }} + - from: + - podSelector: + matchLabels: + app: scanner-v4-matcher + ports: + - port: 5432 + protocol: TCP + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-05-indexer-network-policy.yaml b/4.5.2/central-services/templates/02-scanner-v4-05-indexer-network-policy.yaml new file mode 100644 index 0000000..460801a --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-05-indexer-network-policy.yaml @@ -0,0 +1,90 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-indexer + ingress: + {{- if ._rox.env.centralServices }} + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8443 + protocol: TCP + - from: + - podSelector: + matchLabels: + app: scanner-v4-matcher + ports: + - port: 8443 + protocol: TCP + {{- end }} + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8443 + protocol: TCP + policyTypes: + - Ingress + +{{- if ._rox.scannerV4.exposeMonitoring }} +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: {{ ._rox.scannerV4.indexer.metricsPort }} + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-indexer + policyTypes: + - Ingress +{{- end }} +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer-monitoring-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-indexer + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-05-matcher-network-policy.yaml b/4.5.2/central-services/templates/02-scanner-v4-05-matcher-network-policy.yaml new file mode 100644 index 0000000..fbc3525 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-05-matcher-network-policy.yaml @@ -0,0 +1,74 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._matcherEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-matcher + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-matcher") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-matcher") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-matcher + ingress: + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8443 + protocol: TCP + policyTypes: + - Ingress + +{{- if ._rox.scannerV4.exposeMonitoring }} +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-matcher-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-matcher-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-matcher-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: {{ ._rox.scannerV4.matcher.metricsPort }} + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-matcher + policyTypes: + - Ingress +{{- end }} +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-matcher-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-matcher-monitoring-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-matcher-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-matcher + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-06-db-pvc.yaml b/4.5.2/central-services/templates/02-scanner-v4-06-db-pvc.yaml new file mode 100644 index 0000000..8b27634 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-06-db-pvc.yaml @@ -0,0 +1,66 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.scannerV4._dbEnabled }} + +{{- if ._rox.scannerV4.db.persistence._pvcCfg }} +{{- $pvcCfg := ._rox.scannerV4.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 }} +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: + # this is used for backwards compatibility for operator if there are PVCs without annotation + # owned by the operator it will assume they belong to the deprecated central-db + {{- $labels := dict "target.pvc.stackrox.io" "scanner-v4-db" -}} + {{- include "srox.labels" (list . "persistentvolumeclaim" "scanner-v4-db" $labels) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolumeclaim" "scanner-v4-db") | nindent 4 }} +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} + +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-07-db-deployment.yaml b/4.5.2/central-services/templates/02-scanner-v4-07-db-deployment.yaml new file mode 100644 index 0000000..953cb1c --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-07-db-deployment.yaml @@ -0,0 +1,142 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-db + {{- include "srox.labels" (list . "deployment" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-db + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-db") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "5432" + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-db") | nindent 8 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scannerV4.db._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.db._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.db.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.db.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.db.affinity | nindent 8 }} + {{- if ._rox.scannerV4.db.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.db.hostAliases | nindent 8 }} + {{- end }} + serviceAccountName: scanner-v4 + terminationGracePeriodSeconds: 120 + initContainers: + - name: init-db + image: {{ ._rox.scannerV4.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + - name: POSTGRES_HOST_AUTH_METHOD + value: "scram-sha-256" + - name: POSTGRES_PASSWORD_FILE + value: "/run/secrets/stackrox.io/secrets/password" +{{- if ._rox.env.centralServices }} + - name: SCANNER_DB_INIT_BUNDLE_ENABLED + value: "true" +{{- end }} + command: + - init-entrypoint.sh + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: scanner-v4-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + resources: + {{- ._rox.scannerV4.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + containers: + - name: db + image: {{ ._rox.scannerV4.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + - name: POSTGRES_HOST_AUTH_METHOD + value: "scram-sha-256" + {{- include "srox.envVars" (list . "deployment" "scanner-v4-db" "db") | nindent 8 }} + ports: + - name: tcp-postgresql + containerPort: 5432 + 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.scannerV4.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: config-volume + mountPath: /etc/stackrox.d/config/ + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + - name: shared-memory + mountPath: /dev/shm + securityContext: + fsGroup: 70 + volumes: + - name: disk + {{- toYaml ._rox.scannerV4.db.persistence._volumeCfg | nindent 8 }} + - name: config-volume + configMap: + name: {{ default "scanner-v4-db-config" ._rox.scannerV4.db.configOverride }} + - name: scanner-db-tls-volume + secret: + secretName: scanner-v4-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-templates/scanner-v4-db/postgresql.conf.default */}} + sizeLimit: 750Mi + - name: scanner-v4-db-password + secret: + secretName: scanner-v4-db-password +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-07-indexer-deployment.yaml b/4.5.2/central-services/templates/02-scanner-v4-07-indexer-deployment.yaml new file mode 100644 index 0000000..2be0860 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-07-indexer-deployment.yaml @@ -0,0 +1,174 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-indexer + {{- include "srox.labels" (list . "deployment" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-indexer") | nindent 4 }} +spec: + replicas: {{ ._rox.scannerV4.indexer.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-indexer + strategy: + type: RollingUpdate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-indexer + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-indexer") | nindent 8 }} + annotations: + {{- $annotations := dict "traffic.sidecar.istio.io/excludeInboundPorts" "8443" -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "nonroot-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-indexer" $annotations) | nindent 8 }} + spec: + {{- if ._rox.scannerV4.indexer._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.indexer._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.indexer.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.indexer.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.indexer.affinity | nindent 8 }} + {{- if ._rox.scannerV4.indexer.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.indexer.hostAliases | nindent 8 }} + {{- end }} + containers: + - name: indexer + image: {{ ._rox.scannerV4.indexer.image.fullRef | quote }} + env: + - name: ROX_MEMLIMIT + 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 }} + - name: ROX_METRICS_PORT + value: ":{{- ._rox.scannerV4.indexer.metricsPort -}}" + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + - name: ROX_SECURE_METRICS_PORT + value: ":9091" + {{- end }} + {{- include "srox.envVars" (list . "deployment" "scanner-v4-indexer" "indexer") | nindent 8 }} + resources: + {{- ._rox.scannerV4.indexer._resources | nindent 10 }} + command: + - entrypoint.sh + - --conf=/etc/scanner/config.yaml + ports: + - name: grpc + containerPort: 8443 + {{ if ._rox.scannerV4.exposeMonitoring -}} + - name: monitoring + containerPort: {{ ._rox.scannerV4.indexer.metricsPort }} + {{- end}} + {{- if ._rox.monitoring.openshift.enabled }} + - containerPort: 9091 + name: monitoring-tls + {{- end }} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsNonRoot: true + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /health/readiness + port: 9443 + periodSeconds: 5 + timeoutSeconds: 1 + volumeMounts: + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: etc-ssl-volume + mountPath: /etc/ssl + - name: etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: config-volume + mountPath: /etc/scanner + readOnly: true + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: tmp-volume + mountPath: /tmp + - name: db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner-v4 + volumes: + - name: additional-ca-volume + secret: + optional: true + {{- if ._rox.env.centralServices }} + secretName: additional-ca + {{- else }} + secretName: additional-ca-sensor + {{- end }} + - name: etc-ssl-volume + emptyDir: {} + - name: etc-pki-volume + emptyDir: {} + - name: tls-volume + secret: + secretName: scanner-v4-indexer-tls + - name: config-volume + configMap: + name: scanner-v4-indexer-config + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: tmp-volume + emptyDir: {} + - name: db-password + secret: + secretName: scanner-v4-db-password + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: scanner-v4-indexer-monitoring-tls + {{- end }} + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-07-matcher-deployment.yaml b/4.5.2/central-services/templates/02-scanner-v4-07-matcher-deployment.yaml new file mode 100644 index 0000000..859ea76 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-07-matcher-deployment.yaml @@ -0,0 +1,171 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._matcherEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-matcher + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-matcher + {{- include "srox.labels" (list . "deployment" "scanner-v4-matcher") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-matcher") | nindent 4 }} +spec: + replicas: {{ ._rox.scannerV4.matcher.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-matcher + strategy: + type: RollingUpdate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-matcher + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-matcher") | nindent 8 }} + annotations: + {{- $annotations := dict "traffic.sidecar.istio.io/excludeInboundPorts" "8443" -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "nonroot-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-matcher" $annotations) | nindent 8 }} + spec: + {{- if ._rox.scannerV4.matcher._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.matcher._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.matcher.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.matcher.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.matcher.affinity | nindent 8 }} + {{- if ._rox.scannerV4.matcher.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.matcher.hostAliases | nindent 8 }} + {{- end }} + containers: + - name: matcher + image: {{ ._rox.scannerV4.matcher.image.fullRef | quote }} + env: + - name: ROX_MEMLIMIT + valueFrom: + resourceFieldRef: + {{- /* This is set to requests.memory on purpose in an attempt to minimize memory usage. */}} + resource: requests.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 }} + - name: ROX_METRICS_PORT + value: ":{{- ._rox.scannerV4.matcher.metricsPort -}}" + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + - name: ROX_SECURE_METRICS_PORT + value: ":9091" + {{- end }} + {{- include "srox.envVars" (list . "deployment" "scanner-v4-matcher" "matcher") | nindent 8 }} + resources: + {{- ._rox.scannerV4.matcher._resources | nindent 10 }} + command: + - entrypoint.sh + - --conf=/etc/scanner/config.yaml + ports: + - name: grpc + containerPort: 8443 + {{ if ._rox.scannerV4.exposeMonitoring -}} + - name: monitoring + containerPort: {{ ._rox.scannerV4.matcher.metricsPort }} + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - containerPort: 9091 + name: monitoring-tls + {{- end }} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsNonRoot: true + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /health/readiness + port: 9443 + periodSeconds: 5 + timeoutSeconds: 1 + volumeMounts: + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: etc-ssl-volume + mountPath: /etc/ssl + - name: etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: config-volume + mountPath: /etc/scanner + readOnly: true + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: tmp-volume + mountPath: /tmp + - name: db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner-v4 + volumes: + - name: additional-ca-volume + secret: + optional: true + secretName: additional-ca + - name: etc-ssl-volume + emptyDir: {} + - name: etc-pki-volume + emptyDir: {} + - name: tls-volume + secret: + secretName: scanner-v4-matcher-tls + - name: config-volume + configMap: + name: scanner-v4-matcher-config + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: tmp-volume + emptyDir: {} + - name: db-password + secret: + secretName: scanner-v4-db-password + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: scanner-v4-matcher-monitoring-tls + {{- end }} + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-08-db-service.yaml b/4.5.2/central-services/templates/02-scanner-v4-08-db-service.yaml new file mode 100644 index 0000000..f36bf4d --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-08-db-service.yaml @@ -0,0 +1,43 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-db") | nindent 4 }} +spec: + type: ClusterIP + ports: + - name: tcp-db + port: 5432 + targetPort: 5432 + selector: + app: scanner-v4-db + +{{- if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-db-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-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-v4-db-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-db.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 5432 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-08-indexer-service.yaml b/4.5.2/central-services/templates/02-scanner-v4-08-indexer-service.yaml new file mode 100644 index 0000000..7b3457b --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-08-indexer-service.yaml @@ -0,0 +1,55 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-indexer") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: scanner-v4-indexer-monitoring-tls + {{- end }} +spec: + selector: + app: scanner-v4-indexer + clusterIP: None + ports: + - name: grpc-scanner-v4-indexer + port: 8443 + targetPort: grpc + {{- if ._rox.scannerV4.exposeMonitoring }} + - name: monitoring + port: {{ ._rox.scannerV4.indexer.metricsPort }} + targetPort: monitoring + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: indexer-monitoring-tls + port: 9091 + targetPort: monitoring-tls + {{- end }} + +{{- if ._rox.env.istio }} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-indexer-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-indexer-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-v4-indexer-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-indexer.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8443 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-08-matcher-service.yaml b/4.5.2/central-services/templates/02-scanner-v4-08-matcher-service.yaml new file mode 100644 index 0000000..739fa6c --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-08-matcher-service.yaml @@ -0,0 +1,55 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._matcherEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-matcher + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-matcher") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-matcher") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: scanner-v4-matcher-monitoring-tls + {{- end }} +spec: + selector: + app: scanner-v4-matcher + clusterIP: None + ports: + - name: grpc-scanner-v4-matcher + port: 8443 + targetPort: grpc + {{ if ._rox.scannerV4.exposeMonitoring -}} + - name: monitoring + port: {{ ._rox.scannerV4.matcher.metricsPort }} + targetPort: monitoring + {{- end }} + {{ if ._rox.monitoring.openshift.enabled -}} + - name: matcher-monitoring-tls + port: 9091 + targetPort: monitoring-tls + {{- end }} + +{{- if ._rox.env.istio }} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-matcher-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-matcher-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-v4-matcher-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-matcher.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8443 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-09-indexer-hpa.yaml b/4.5.2/central-services/templates/02-scanner-v4-09-indexer-hpa.yaml new file mode 100644 index 0000000..91e4832 --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-09-indexer-hpa.yaml @@ -0,0 +1,20 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled (not ._rox.scannerV4.indexer.autoscaling.disable) }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner-v4-indexer") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scannerV4.indexer.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scannerV4.indexer.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner-v4-indexer + targetCPUUtilizationPercentage: 150 +{{- end }} diff --git a/4.5.2/central-services/templates/02-scanner-v4-09-matcher-hpa.yaml b/4.5.2/central-services/templates/02-scanner-v4-09-matcher-hpa.yaml new file mode 100644 index 0000000..d90bfcb --- /dev/null +++ b/4.5.2/central-services/templates/02-scanner-v4-09-matcher-hpa.yaml @@ -0,0 +1,20 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._matcherEnabled (not ._rox.scannerV4.matcher.autoscaling.disable) }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner-v4-matcher + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner-v4-matcher") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner-v4-matcher") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scannerV4.matcher.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scannerV4.matcher.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner-v4-matcher + targetCPUUtilizationPercentage: 150 +{{- end }} diff --git a/4.5.2/central-services/templates/99-generated-values-secret.yaml b/4.5.2/central-services/templates/99-generated-values-secret.yaml new file mode 100644 index 0000000..b3499e8 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/99-openshift-monitoring.yaml b/4.5.2/central-services/templates/99-openshift-monitoring.yaml new file mode 100644 index 0000000..a2a6f28 --- /dev/null +++ b/4.5.2/central-services/templates/99-openshift-monitoring.yaml @@ -0,0 +1,149 @@ +{{- 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 + +--- + +{{- /* +The ServiceMonitor is placed into the openshift-monitoring namespace to comply with the +OpenShift monitoring namespace label requirements. This is an exception to the rule +that leaking resources into system namespaces should be avoided. +*/}} +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 }}" + +--- + +{{- /* +TODO(ROX-22188): Switch to a ClusterRoleBinding to avoid leaking to kube-system 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 }}" + +--- + +{{- /* +The PrometheusRule is placed into the openshift-monitoring namespace to comply with the +OpenShift monitoring namespace label requirements. This is an exception to the rule +that leaking resources into system namespaces should be avoided. +Note that we have an exception for this resource for the SRE webhook validation for +managed OpenShift clusters. +*/}} +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.5.2/central-services/templates/99-shared-openshift-monitoring.yaml b/4.5.2/central-services/templates/99-shared-openshift-monitoring.yaml new file mode 100644 index 0000000..2035970 --- /dev/null +++ b/4.5.2/central-services/templates/99-shared-openshift-monitoring.yaml @@ -0,0 +1,65 @@ +{{- include "srox.init" . -}} +{{- if ._rox.monitoring.openshift.enabled -}} + {{- if (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: "scanner-v4-monitor-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "servicemonitor" (print "scanner-v4-monitor-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "servicemonitor" (print "scanner-v4-monitor-" .Release.Namespace)) | nindent 4 }} +spec: + endpoints: + {{- if ._rox.scannerV4._indexerEnabled }} + - interval: 30s + path: metrics + port: indexer-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: "scanner-v4-indexer.{{ .Release.Namespace }}.svc" + {{- end }} + {{- if ._rox.scannerV4._matcherEnabled }} + - interval: 30s + path: metrics + port: matcher-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: "scanner-v4-matcher.{{ .Release.Namespace }}.svc" + {{- end }} + selector: + matchLabels: + app.kubernetes.io/component: scanner-v4 + namespaceSelector: + matchNames: + - "{{ .Release.Namespace }}" +--- +{{/* TODO(ROX-22188): Switch to a ClusterRoleBinding to avoid leaking to + kube-system namespace. */ -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "rhacs-scanner-v4-auth-reader-{{ .Release.Namespace }}" + namespace: kube-system + labels: + {{- include "srox.labels" (list . "rolebinding" (print "rhacs-scanner-v4-auth-reader-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" (print "rhacs-scanner-v4-auth-reader-" .Release.Namespace)) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: scanner-v4 + namespace: "{{ .Release.Namespace }}" + {{- end }} +{{- end }} diff --git a/4.5.2/central-services/templates/NOTES.txt b/4.5.2/central-services/templates/NOTES.txt new file mode 100644 index 0000000..9f07746 --- /dev/null +++ b/4.5.2/central-services/templates/NOTES.txt @@ -0,0 +1,68 @@ +{{- $_ := include "srox.init" . -}} + +StackRox Central Services has been installed. + + +Central Services Configuration Summary: + + Stackrox Version: {{ .Chart.AppVersion }} + Kubernetes Version: {{ ._rox._apiServer.version }} + Kubernetes Namespace: {{ .Release.Namespace }} + Helm Release Name: {{ .Release.Name }} + OpenShift Cluster: {{ if eq ._rox.env.openshift 0 -}} false {{ else -}} {{ ._rox.env.openshift }} {{ end }} + Scanner V4: {{ if ._rox._scannerV4Enabled -}} enabled {{- else -}} disabled {{- end }} +{{- if and ._rox._scannerV4Enabled ._rox._scannerV4Volume }} + Scanner V4 DB Volume: {{ ._rox._scannerV4Volume }} +{{- end }} + +{{ 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.5.2/central-services/templates/_central_endpoints.tpl b/4.5.2/central-services/templates/_central_endpoints.tpl new file mode 100644 index 0000000..646d9a6 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_central_setup.tpl b/4.5.2/central-services/templates/_central_setup.tpl new file mode 100644 index 0000000..e3e8b5f --- /dev/null +++ b/4.5.2/central-services/templates/_central_setup.tpl @@ -0,0 +1,146 @@ +{{/* + 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 }} + {{ if $pvcCfg.storageClass}} + {{ $_ = set $._rox._state "referencedStorageClasses" (mustAppend $._rox._state.referencedStorageClasses $pvcCfg.storageClass | uniq) }} + {{ 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 }} + {{ if $dbPVCCfg.storageClass}} + {{ $_ = set $._rox._state "referencedStorageClasses" (mustAppend $._rox._state.referencedStorageClasses $dbPVCCfg.storageClass | uniq) }} + {{ 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.5.2/central-services/templates/_crypto.tpl b/4.5.2/central-services/templates/_crypto.tpl new file mode 100644 index 0000000..4ac1fac --- /dev/null +++ b/4.5.2/central-services/templates/_crypto.tpl @@ -0,0 +1,247 @@ +{{/* + 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 }} + {{ $msg := list }} + {{ $msg = append $msg (printf "Tried to generate certificate for %s, but no CA certificate is available." $spec.CN) }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "Providing the CA is required when certificates for new components need to be issued. This can happen, for instance, when enabling a new component such as Scanner V4 using 'helm upgrade'." }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "If the CA was generated by the Helm chart during initial installation, you need to retrieve these auto-generated values from the cluster and provide them to the 'helm upgrade' command. A command for retrieving the auto-generated values was included in the post-installation notes of the central-services Helm chart." }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "If the CA was generated outside of the Helm chart and provided during the installation of the central-services chart, then the same must be done when executing 'helm upgrade'. This can be achieved conveniently by specifying the '--reuse-values' flag to 'helm upgrade'." }} + {{ include "srox.fail" (join "\n" $msg) }} + {{ 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.5.2/central-services/templates/_dict.tpl b/4.5.2/central-services/templates/_dict.tpl new file mode 100644 index 0000000..bf14a6d --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_expand.tpl b/4.5.2/central-services/templates/_expand.tpl new file mode 100644 index 0000000..9ed2531 --- /dev/null +++ b/4.5.2/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 assumed 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._expandSingle $ $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.5.2/central-services/templates/_format.tpl b/4.5.2/central-services/templates/_format.tpl new file mode 100644 index 0000000..745fe47 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_helpers.tpl b/4.5.2/central-services/templates/_helpers.tpl new file mode 100644 index 0000000..69e5316 --- /dev/null +++ b/4.5.2/central-services/templates/_helpers.tpl @@ -0,0 +1,94 @@ +{{/* + 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 -}} + +{{- define "srox.checkVersionRequirements" -}} + {{- $minHelmVersion := "3.9.0" -}} + {{- $ := . -}} + + {{- $helmVersion := "" -}} + {{- if and (not (kindIs "invalid" $.Capabilities.HelmVersion)) $.Capabilities.HelmVersion -}} + {{- $helmVersion = $.Capabilities.HelmVersion.Version -}} + {{- end -}} + + {{- if empty $helmVersion -}} + {{- $msg := printf "Failed to retrieve Helm version. Please make sure you are running Helm >= v%s." $minHelmVersion -}} + {{- if $._rox.allowUnsupportedHelmVersion -}} + {{- include "srox.warn" (list $ $msg) -}} + {{- else -}} + {{- include "srox.fail" $msg -}} + {{- end -}} + {{- else if semverCompare (printf "< %s" $minHelmVersion) $helmVersion -}} + {{- $msg := printf "Helm version requirements not satisfied. Your Helm %s is too old. Please update to Helm >= v%s." $helmVersion $minHelmVersion -}} + {{- if $._rox.allowUnsupportedHelmVersion -}} + {{- include "srox.warn" (list $ $msg) -}} + {{- else -}} + {{- include "srox.fail" $msg -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/4.5.2/central-services/templates/_image-pull-secrets.tpl b/4.5.2/central-services/templates/_image-pull-secrets.tpl new file mode 100644 index 0000000..e758a70 --- /dev/null +++ b/4.5.2/central-services/templates/_image-pull-secrets.tpl @@ -0,0 +1,105 @@ +{{/* + srox.configureImagePullSecrets $ $cfgName $imagePullSecrets $secretResourceName $defaultSecretNames $namespace + + Configures image pull secrets. + + Note: This function must be called late in srox.init, as we rely on "srox.configureImage" to collect the + set of all referenced images first. + + This function enriches $imagePullSecrets based on the exposed configuration parameters to contain: + + 1. Optionally (i.e. only if $imagePullSecrets contains a username), a `_dockerAuths` field, containing a map + from registry URLs to settings that contain login credentials. + The map contains registries for all images passed so far to srox.configureImage invocations. + + 2. A `_names` field, containing a list of Kubernetes secret names. The chart templates then use this field + to populate imagePullSecrets lists in ServiceAccount objects. + + The list contains the following secrets: + + - Secrets referenced via $imagePullSecrets.useExisting (unconditonally). + - Image pull secrets associated with the default service account (unless + $imagePullSecrets.useFromDefaultServiceAccount was set to false by the user). + - $secretResourceName, i.e. the secret optionally created by the chart templates. This name will be included + in the list either if username/password is provided (i.e. whe the chart ensures presence of the secret) OR + if the resource already exists in the namespace (for backward compatibility with versions 4.3 or earlier). + - $defaultSecretNames, only if the corresponding secrets already exist in the namespace (again, for backward + compatibility). + + Additionally, this function fails execution if the list resulting from first three bullet points + combined is empty. + +*/}} + +{{ 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 }} + +{{ if $imagePullSecrets._username }} + {{/* When username is present, existence of $secretResourceName will be assured by the templates; add to the list. */}} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretResourceName }} + + {{ $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 }} + +{{ 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 }} + +{{/* For backward compatibility, include those secrets which already exist. + In manifest installation mode, include them unconditionally, for lack of a better way. +*/}} +{{ range $secretName := append $defaultSecretNames $secretResourceName }} + {{ $secret := dict }} + {{ include "srox.safeLookup" (list $ $secret "v1" "Secret" $namespace $secretName) }} + {{ if or (eq $._rox.env.installMethod "manifest") $secret.result }} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretName }} + {{ end }} +{{ end }} + +{{ $imagePullSecretNames = $imagePullSecretNames | uniq | sortAlpha }} +{{ $_ := set $imagePullSecrets "_names" $imagePullSecretNames }} + +{{ end }} diff --git a/4.5.2/central-services/templates/_images.tpl b/4.5.2/central-services/templates/_images.tpl new file mode 100644 index 0000000..dced29d --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_init.tpl b/4.5.2/central-services/templates/_init.tpl new file mode 100644 index 0000000..6e6ab38 --- /dev/null +++ b/4.5.2/central-services/templates/_init.tpl @@ -0,0 +1,310 @@ +{{/* + 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 }} +{{ $_ = set $state "customCertGen" false }} +{{ $_ = set $state "generated" dict }} +{{ $_ = set $state "generatedName" $generatedName }} +{{ $_ = set $state "notes" list }} +{{ $_ = set $state "warnings" list }} +{{ $_ = set $state "referencedImages" dict }} +{{ $_ = set $state "referencedStorageClasses" list }} +{{ $_ = set $._rox "_state" $state }} + +{{- include "srox.checkVersionRequirements" $ -}} + +{{ $configShape := $.Files.Get "internal/config-shape.yaml" | fromYaml }} +{{ $configShapeScanner := $.Files.Get "internal/scanner-config-shape.yaml" | fromYaml }} +{{ $_ = include "srox.mergeInto" (list $configShape $configShapeScanner) }} +{{ $configShapeScannerV4 := $.Files.Get "internal/scanner-v4-config-shape.yaml" | fromYaml }} +{{ $_ = include "srox.mergeInto" (list $configShape $configShapeScannerV4) }} + +{{ $_ = include "srox.mergeInto" (list $rox $configShape (tpl ($.Files.Get "internal/bootstrap-defaults.yaml.tpl") . | fromYaml)) }} + +{{ $_ = set $._rox "_configShape" $configShape }} + +{{ $_ = include "srox.loadAnnotationTemplates" $ }} + +{{/* + 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 $) }} + +{{ include "srox.setInstallMethod" (list $) }} + +{{/* 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) }} + +{{/* Add environment information which should not be modifiable by the user. */}} +{{ $_ := set $env "centralServices" true }} + +{{/* 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 }} + +{{/* + ScannerV4 setup. + */}} + +{{ $scannerV4Cfg := $._rox.scannerV4 }} +{{ include "srox.scannerV4Init" (list $ $scannerV4Cfg) }} + +{{ if $._rox.scannerV4._dbEnabled }} + {{ include "srox.scannerV4Volume" $ }} +{{ 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. + + Note: This must happen late, as we rely on "srox.configureImage" to collect the + set of all referenced images first. + + 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) }} + +{{/* 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.5.2/central-services/templates/_injected-ca-bundle.tpl b/4.5.2/central-services/templates/_injected-ca-bundle.tpl new file mode 100644 index 0000000..f831139 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_labels.tpl b/4.5.2/central-services/templates/_labels.tpl new file mode 100644 index 0000000..703c8ae --- /dev/null +++ b/4.5.2/central-services/templates/_labels.tpl @@ -0,0 +1,31 @@ +{{/* + srox._labels $ $labels $extraLabels $objType $objName $forPod + + Writes all applicable [pod] labels (including default labels) for $objType/$objName + into $labels. Pod labels are written iff $forPod is true. + The dict $extraLabels can be used for specifying additional labels which + can be modified by the user using `customize` entries before before they are added to $labels. + */}} +{{ define "srox._labels" }} +{{ $ := index . 0 }} +{{ $labels := index . 1 }} +{{ $extraLabels := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $forPod := index . 5 }} +{{ $_ := 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-z0-9-]+)-\\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 $extraLabels $objType $objName $metadataNames) }} +{{ end }} diff --git a/4.5.2/central-services/templates/_lookup.tpl b/4.5.2/central-services/templates/_lookup.tpl new file mode 100644 index 0000000..2dc0aa9 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_metadata.tpl b/4.5.2/central-services/templates/_metadata.tpl new file mode 100644 index 0000000..e97d70d --- /dev/null +++ b/4.5.2/central-services/templates/_metadata.tpl @@ -0,0 +1,307 @@ +{{/* + srox.labels $ $objType $objName [ $extraLabels ] + + Format labels for $objType/$objName as YAML. This takes into consideration the $extraLabels, + if provided, plus labels added using the generic `customize` configuration mechanism. + Note that provided $extraLabels can be modified by the user via `customize`. + + Note that pod resources are treated specially when it comes to customizing labels. + For enabling the user to define labels which shall only be applied to pods belonging + to a specific workload, the following rules apply for the Helm chart templates: + + - use the "srox.podLabels" template for injecting labels into pod templates and + - use the "srox.labels" template for injecting labels into all other resources. + + The user of the Helm charts may define `labels` within the `customize` structure for any + resources rendered as part of the charts. Such labels defined for workloads, e.g. a deployment, + will be injected into the deployment resource *and* will also be inherited to the pods belonging + to the workload. On the other hand, labels defined via `podLabels` are only meaningful for workload + resources and are only injected into the respective pods. + */}} +{{- define "srox.labels" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraLabels := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraLabels = default dict (index . 3) -}} + {{- end -}} + {{- $labels := dict -}} + {{- $_ := include "srox._labels" (list $ $labels $extraLabels $objType $objName false) }} + {{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.podLabels $ $objType $objName [ $extraLabels ] + + Format pod labels for $objType/$objName as YAML. This takes into consideration the $extraLabels, + if provided, plus labels added using the generic `customize` configuration mechanism. + Note that provided $extraLabels can be modified by the user via `customize`. + + See the description above for the template "srox.labels" for an explanation of the differences between + "srox.labels" and "srox.podLabels". + */}} +{{- define "srox.podLabels" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraLabels := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraLabels = default dict (index . 3) -}} + {{- end -}} + {{- $labels := dict -}} + {{- $_ := include "srox._labels" (list $ $labels $extraLabels $objType $objName true) }} + {{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.annotations $ $objType $objName [ $extraAnnotations ] + + Format annotations for $objType/$objName as YAML. This takes into consideration the $extraAnnotations, + if provided, plus annotations added using the generic `customize` configuration mechanism. + Note that provided $extraAnnotations can be modified by the user via `customize`. + + Note that pod resources are treated specially when it comes to customizing annotations. + For enabling the user to define annotations which shall only be applied to pods belonging + to a specific workload, the following rules apply for the Helm chart templates: + + - use the "srox.podAnnotations" template for injecting annotations into pod templates and + - use the "srox.annotations" template for injecting annotations into all other resources. + + The user of the Helm charts may define `annotations` within the `customize` structure for any + resources rendered as part of the charts. Such annotations defined for workloads, e.g. a deployment, + will be injected into the deployment resource *and* will also be inherited to the pods belonging + to the workload. On the other hand, annotations defined via `podAnnotations` are only meaningful + for workload resources and are only injected into the respective pods. + */}} +{{- define "srox.annotations" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraAnnotations := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraAnnotations = default dict (index . 3) -}} + {{- end -}} + {{- $annotations := dict -}} + {{- $_ := include "srox._annotations" (list $ $annotations $extraAnnotations $objType $objName false) -}} + {{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.podAnnotations $ $objType $objName [ $extraAnnotations ] + + Format pod annotations for $objType/$objName as YAML. This takes into consideration the $extraAnnotations, + if provided, plus annotations added using the generic `customize` configuration mechanism. + Note that provided $extraAnnotations can be modified by the user via `customize`. + + See the description above for the template "srox.annotations" for an explanation of the differences between + "srox.annotations" and "srox.podAnnotations". + */}} +{{- define "srox.podAnnotations" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraAnnotations := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraAnnotations = default dict (index . 3) -}} + {{- end -}} + {{- $annotations := dict -}} + {{- $_ := include "srox._annotations" (list $ $annotations $extraAnnotations $objType $objName 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 $extraAnnotations $objType $objName $forPod + + Writes all applicable [pod] annotations (including default annotations) for + $objType/$objName into $annotations. Pod labels are written iff $forPod is true. + The dict $extraAnnotations can be used for specifying additional annotations which + can be modified by the user using `customize` entries before before they are added to $annotations. + */}} +{{ define "srox._annotations" }} +{{ $ := index . 0 }} +{{ $annotations := index . 1 }} +{{ $extraAnnotations := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $forPod := index . 5 }} +{{ $_ := 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 $extraAnnotations $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 dict $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 $extraMetadata $objType $objName $metadataNames + + Writes custom key/value metadata to $metadata by consulting $extraMetadata in addition to 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 }} +{{ $extraMetadata := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $metadataNames := index . 5 }} + +{{ $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 $extraMetadata $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. */ -}} + {{- if hasPrefix "stackrox-" $name -}} + {{- printf "%s-%s" $._rox.globalPrefix (trimPrefix "stackrox-" $name) -}} + {{- else if hasPrefix "stackrox:" $name -}} + {{- printf "%s:%s" $._rox.globalPrefix (trimPrefix "stackrox:" $name) -}} + {{- else -}} + {{- include "srox.fail" (printf "Unknown naming convention for global resource %q." $name) -}} + {{- end -}} +{{- 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 -}} + +{{/* + srox.getAnnotationTemplate . $name $out + + Retrieve the annotation template with the given $name and store it in the provided $out parameter. + */}} +{{ define "srox.getAnnotationTemplate" }} + {{ $ := index . 0 }} + {{ $name := index . 1 }} + {{ $out := index . 2 }} + {{ if kindIs "invalid" $._rox._annotationTemplates }} + {{ include "srox.fail" "Annotation templates not initialized" }} + {{ end }} + {{ $annotationTemplates := get $._rox._annotationTemplates $name }} + {{ if not $annotationTemplates }} + {{ include "srox.fail" (printf "Annotation template %q does not exist in internal/annotations/" $name) }} + {{ end }} + {{ range $key, $value := $annotationTemplates }} + {{ $_ := set $out $key $value }} + {{ end }} +{{ end }} + +{{/* + srox.loadAnnotationTemplates . + + Load the annotation templates from `internal/annotations` and store them within $._rox. + The templates can later be retrieved with `srox.getAnnotationTemplate`. + */}} +{{ define "srox.loadAnnotationTemplates" }} + {{ $ := . }} + {{ if kindIs "invalid" $._rox._annotationTemplates }} + {{ $_ := set $._rox "_annotationTemplates" dict }} + {{ end }} + {{ range $fileName, $annotations := $.Files.Glob "internal/annotations/*.yaml" }} + {{ $name := trimSuffix ".yaml" (base $fileName) }} + {{ $_ := set $._rox._annotationTemplates $name ($annotations | toString | fromYaml) }} + {{ end }} +{{ end }} diff --git a/4.5.2/central-services/templates/_openshift.tpl b/4.5.2/central-services/templates/_openshift.tpl new file mode 100644 index 0000000..85201cb --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_psp.tpl b/4.5.2/central-services/templates/_psp.tpl new file mode 100644 index 0000000..bffb2a0 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_pvcs.tpl b/4.5.2/central-services/templates/_pvcs.tpl new file mode 100644 index 0000000..ad40204 --- /dev/null +++ b/4.5.2/central-services/templates/_pvcs.tpl @@ -0,0 +1,20 @@ +{{/* + srox.getPVCs $ + + This function attempts to retrieve information about all available PVCs in the + current namespace + + $._rox.env.pvcs.names: A list of PVC names. + */}} +{{- define "srox.getPVCs" -}} + + {{- $ := index . 0 -}} + {{- $pvcNames := list -}} + {{- $lookupResult := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupResult "v1" "PersistentVolumeClaim" $._rox._namespace "") -}} + {{- range $pvc := get ($lookupResult.result | default dict) "items" | default list -}} + {{- $pvcNames = append $pvcNames $pvc.metadata.name -}} + {{- end -}} + {{- $_ := set $._rox.env.pvcs "names" $pvcNames -}} + +{{- end -}} diff --git a/4.5.2/central-services/templates/_reporting.tpl b/4.5.2/central-services/templates/_reporting.tpl new file mode 100644 index 0000000..621e284 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_scanner-v4_init.tpl b/4.5.2/central-services/templates/_scanner-v4_init.tpl new file mode 100644 index 0000000..323bfa4 --- /dev/null +++ b/4.5.2/central-services/templates/_scanner-v4_init.tpl @@ -0,0 +1,179 @@ +{{/* + srox.scannerV4Init . $scannerV4Config + + Initializes the Scanner v4 configuration. The scanner chart has two modes: Indexer and Matcher. + In Indexer mode, the Scanner pulls images and analyzes them to determine the base OS and installed packages + (i.e. it indexes the images). + In Matcher mode, the Scanner matches the found packages to known vulnerabilities to produce a Vulnerability Report. + Both modes require access to a PostgreSQL database. + + StackRox's Central service has two Scanner deployments: a Scanner running in Indexer mode and another + running in Matcher mode. In this context, the Helm chart can create its own certificates. + + StackRox's Secured Cluster services may deploy the Scanner in Indexer mode, only. + This would be done to access registries inaccessible to the Central cluster. + In this context, the Helm chart does not generate its own certificates. + + $scannerV4Config contains all values which are configured by the user. The structures can be viewed in the respective + config-shape. See internal/scanner-v4-config-shape.yaml. + */}} + +{{ define "srox.scannerV4Init" }} + +{{ $ := index . 0 }} +{{ $scannerV4Cfg := index . 1 }} +{{ $_ := false }} + +{{/* Sanity check. */}} +{{- if not (or (eq $.Chart.Name "stackrox-central-services") (eq $.Chart.Name "stackrox-secured-cluster-services")) -}} + {{- include "srox.fail" (printf "Unexpected Helm chart name %q." $.Chart.Name) -}} +{{- end -}} + +{{ $componentsCentralChart := dict "indexer" true "matcher" true }} +{{ $componentsSecuredClusterChart := dict "indexer" true "matcher" false }} + +{{/* These will be propagated up. */}} +{{ $components := dict "indexer" false "matcher" false }} +{{ $dbEnabled := false }} + +{{- if not $scannerV4Cfg.disable }} + {{/* Scanner V4 is switched on. */}} + + {{/* Scanner V4 component configuration depends on the chart. */}} + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{- $components = $componentsCentralChart -}} + {{- else -}} + {{- $components = $componentsSecuredClusterChart -}} + {{/* scannerV4.indexer.disable can be used to disable the deployment of indexer. + This is required for the operator use-case. */}} + {{- if $scannerV4Cfg.indexer.disable -}} + {{- $_ = set $components "indexer" false -}} + {{- end -}} + {{- end -}} + + {{/* Configure images, certificates and passwords as required. */}} + {{ if or (get $components "indexer") (get $components "matcher") }} + {{ include "srox.configureImage" (list $ $scannerV4Cfg.image) }} + {{ end }} + + {{ if get $components "indexer" }} + {{ $_ := set $scannerV4Cfg.indexer "image" $scannerV4Cfg.image }} + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{/* Only generate certificate when installing central-services. + For secured-cluster-services we don't configure certificates here, + instead they will be distributed at runtime by Sensor and Central. */}} + {{- if kindIs "invalid" $._rox.scannerV4.indexer.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-indexer-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.indexer.serviceTLS "generate" true -}} + {{- end -}} + {{- end -}} + {{- end }} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_INDEXER_SERVICE: Scanner V4 Indexer" "dnsBase" "scanner-v4-indexer" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.indexer.serviceTLS" $cryptoSpec) }} + {{- end -}} + {{ end }} + + {{ if get $components "matcher" }} + {{ $_ := set $scannerV4Cfg.matcher "image" $scannerV4Cfg.image }} + {{- if kindIs "invalid" $._rox.scannerV4.matcher.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-matcher-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.matcher.serviceTLS "generate" true -}} + {{- end -}} + {{- end }} + {{- end }} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_MATCHER_SERVICE: Scanner V4 Matcher" "dnsBase" "scanner-v4-matcher" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.matcher.serviceTLS" $cryptoSpec) }} + {{ end }} + + {{ if or (get $components "indexer") (get $components "matcher") }} + {{- if kindIs "invalid" $._rox.scannerV4.db.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-db-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.db.serviceTLS "generate" true -}} + {{- end -}} + {{- end -}} + {{- end }} + {{- if kindIs "invalid" $._rox.scannerV4.db.password.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-db-password") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.db.password "generate" true -}} + {{- end -}} + {{- end }} + + {{ include "srox.configureImage" (list $ $scannerV4Cfg.db.image) }} + {{ include "srox.configurePassword" (list $ "scannerV4.db.password") }} + + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{/* Only generate certificate when installing central-services. */}} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_DB_SERVICE: Scanner V4 DB" "dnsBase" "scanner-v4-db" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.db.serviceTLS" $cryptoSpec) }} + {{- end -}} + {{ end }} + +{{- if eq $.Chart.Name "stackrox-secured-cluster-services" -}} + {{/* Special handling for the secured-cluster-services chart in case it gets deployed + to the same namespace as central-services. */}} + {{ $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-v4-indexer from this chart and configuring sensor to use existing scanner-v4-indexer instance, if any.") }} + {{ $_ := set $components "indexer" false }} + {{ end }} +{{- end }} + +{{- end -}} {{/* if not $scannerV4Cfg.disable */}} + +{{/* Propagate information about which Scanner V4 components to deploy. */}} +{{- $_ := set $._rox "_scannerV4Enabled" (not $scannerV4Cfg.disable) -}} +{{- $_ := set $._rox.scannerV4 "_indexerEnabled" (get $components "indexer") -}} +{{- $_ := set $._rox.scannerV4 "_matcherEnabled" (get $components "matcher") -}} +{{- if or (get $components "indexer") (get $components "matcher") -}} + {{- $_ := set $._rox.scannerV4 "_dbEnabled" true -}} +{{- end -}} + +{{/* Provide some human-readable feedback regarding the Scanner V4 configuration to the user installing the Helm chart. */}} +{{- if and (get $components "indexer") (not (get $components "matcher")) -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "indexer" -}} +{{- else if and (not (get $components "indexer")) (get $components "matcher") -}} + {{/* Just here for completeness, not allowed currently. */}} + {{- $_ = set $._rox.scannerV4 "_installMode" "matcher" -}} +{{- else if and (get $components "indexer") (get $components "matcher") -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "indexer and matcher" -}} +{{- else -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "" -}} +{{- end -}} + +{{- if not $scannerV4Cfg.disable }} + {{- if eq $._rox.scannerV4._installMode "" }} + {{ include "srox.note" (list $ (printf "Scanner V4 is enabled and Scanner V4 components are already deployed.")) }} + {{- else }} + {{ include "srox.note" (list $ (printf "Scanner V4 is enabled and the following Scanner V4 components will be deployed: %s" $._rox.scannerV4._installMode)) }} + {{- end }} +{{- end }} + +{{- end -}} diff --git a/4.5.2/central-services/templates/_scanner-v4_volume.tpl b/4.5.2/central-services/templates/_scanner-v4_volume.tpl new file mode 100644 index 0000000..4d2a14b --- /dev/null +++ b/4.5.2/central-services/templates/_scanner-v4_volume.tpl @@ -0,0 +1,113 @@ +{{/* + srox.scannerV4Volume $ + + Configures and initializes Scanner v4 persistence. + */}} +{{ define "srox.scannerV4Volume" }} +{{ $ := . }} +{{ $_ := set $ "_rox" $._rox }} + +{{ $scannerV4DBCfg := $._rox.scannerV4.db }} + +{{/* + Scanner v4 DB Volume config setup. + */}} +{{ $scannerV4DBVolumeCfg := dict }} +{{ $scannerV4DBVolumeHumanReadable := "" }} +{{ $pvcConfigShape := $._rox._configShape.scannerV4.db.persistence.persistentVolumeClaim }} +{{ $pvcDefaults := dict }} +{{- if eq $.Chart.Name "stackrox-central-services" -}} + {{ $pvcDefaults = $._rox._defaults.scannerV4DBPVCDefaults }} +{{- else -}} + {{ $pvcDefaults = $._rox.scannerV4DBPVCDefaults }} +{{- end -}} + +{{ $extraSettings := dict "createClaim" .Release.IsInstall }} +{{ if $._rox.env.storageClasses.default }} + {{ $_ = set $extraSettings "storageClass" $._rox.env.storageClasses.default }} +{{ end }} + +{{/* First we check that the persistence configuration provided by the user is sane in the sense that only one of the + supported backends emptyDir/hostPath/PVC is configured. */}} +{{ $persistenceBackendsConfigured := list }} +{{ if $scannerV4DBCfg.persistence.none }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured "emptyDir" }} +{{ end }} +{{ if $scannerV4DBCfg.persistence.hostPath }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured "hostPath" }} +{{ end }} +{{ if not (deepEqual $pvcConfigShape $scannerV4DBCfg.persistence.persistentVolumeClaim) }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured (printf "PVC:%v" $scannerV4DBCfg.persistence.persistentVolumeClaim) }} +{{ end }} + +{{/* Sanity checks and defaulting. */}} +{{ if empty $persistenceBackendsConfigured }} + {{/* No persistence backend configured, pick a reasonable default. */}} + {{ if or $._rox.env.storageClasses.default (eq $.Chart.Name "stackrox-central-services") }} + {{/* Either a default StorageClass has been detected or we are currently rendering central-services. + In both cases we configure a PVC as persistence backend. */}} + {{ if $._rox.env.storageClasses.default }} + {{ include "srox.note" (list $ "Default StorageClass detected, a PVC will be used for Scanner V4 DB persistence.") }} + {{ else }} + {{ include "srox.note" (list $ "A PVC will be used for Scanner V4 DB persistence.") }} + {{ end }} + {{ if has $pvcDefaults.claimName $._rox.env.pvcs.names }} + {{ $_ = set $extraSettings "createClaim" false }} + {{ else }} + {{ $_ = set $extraSettings "createClaim" true }} + {{ end }} + {{ $_ = include "srox.mergeInto" (list $scannerV4DBCfg.persistence.persistentVolumeClaim $pvcConfigShape $extraSettings $pvcDefaults) }} + {{ else }} + {{/* No default StorageClass detected, currently rendering secured-cluster-services chart. */}} + {{ if has $pvcDefaults.claimName $._rox.env.pvcs.names }} + {{ include "srox.note" (list $ (printf "A PVC named %s already exists, will keep using it for Scanner V4 DB persistence." $pvcDefaults.claimName)) }} + {{ $_ = set $extraSettings "createClaim" false }} + {{ $_ = include "srox.mergeInto" (list $scannerV4DBCfg.persistence.persistentVolumeClaim $pvcConfigShape $extraSettings $pvcDefaults) }} + {{ else }} + {{/* Fallback to emptyDir. */}} + {{ include "srox.warn" (list $ (printf "No default StorageClass detected, using emptyDir as persistence backend for Scanner V4 DB. It is highly recommended to use a PVC instead. Please check the documentation for more information on this." )) }} + {{ $_ = set $scannerV4DBCfg.persistence "none" true }} + {{ end }} + {{ end }} +{{ else if gt (len $persistenceBackendsConfigured) 1 }} + {{ include "srox.fail" (printf "Invalid persistence configuration for Scanner V4 DB: more than one persistence backend configured (%v)" $persistenceBackendsConfigured) }} +{{ end }} + + +{{/* Update $scannerV4DBVolumeCfg depending on configured persistence backend. */}} +{{ if $scannerV4DBCfg.persistence.none }} + {{ include "srox.warn" (list $ "Persistence for Scanner V4 DB is turned off (it is using an emptyDir volume). Every deletion of the StackRox Scanner V4 DB pod will cause you to lose all your data. This is STRONGLY recommended against.") }} + {{ $_ := set $scannerV4DBVolumeCfg "emptyDir" dict }} + {{ $scannerV4DBVolumeHumanReadable = "emptyDir" }} +{{ else if $scannerV4DBCfg.persistence.hostPath }} + {{ if not $scannerV4DBCfg.nodeSelector }} + {{ include "srox.warn" (list $ "A hostPath volume will be used by the Scanner V4 DB. At the same time no node selector is specified. This is unlikely to work reliably.") }} + {{ end }} + {{ $_ := set $scannerV4DBVolumeCfg "hostPath" (dict "path" $scannerV4DBCfg.persistence.hostPath) }} + {{ $scannerV4DBVolumeHumanReadable = printf "hostPath (%s)" $scannerV4DBCfg.persistence.hostPath}} +{{ else }} + {{ if kindIs "invalid" $scannerV4DBCfg.persistence.persistentVolumeClaim.storageClass }} + {{ include "srox.note" (list $ "A PVC using the default storage class will be used for the Scanner V4 DB.") }} + {{ else }} + {{ include "srox.note" (list $ (printf "A PVC using the storage class %q will be used for the Scanner V4 DB." $scannerV4DBCfg.persistence.persistentVolumeClaim.storageClass)) }} + {{ end }} + {{ $scannerV4DBPVCCfg := $scannerV4DBCfg.persistence.persistentVolumeClaim }} + {{ $_ := include "srox.mergeInto" (list $scannerV4DBPVCCfg $extraSettings $pvcDefaults) }} + {{ $_ = set $scannerV4DBVolumeCfg "persistentVolumeClaim" (dict "claimName" $scannerV4DBPVCCfg.claimName) }} + {{ if $scannerV4DBPVCCfg.createClaim }} + {{ $_ = set $scannerV4DBCfg.persistence "_pvcCfg" $scannerV4DBPVCCfg }} + {{ end }} + {{ if $scannerV4DBPVCCfg.storageClass }} + {{ $_ = set $._rox._state "referencedStorageClasses" (mustAppend $._rox._state.referencedStorageClasses $scannerV4DBPVCCfg.storageClass | uniq) }} + {{ end }} + {{ $scannerV4DBVolumeHumanReadable = printf "PVC (%s)" $scannerV4DBPVCCfg.claimName }} +{{ end }} + +{{ $allPersistenceMethods := keys $scannerV4DBVolumeCfg | sortAlpha }} +{{ if ne (len $allPersistenceMethods) 1 }} +{{ end }} + +{{ $_ = set $scannerV4DBCfg.persistence "_volumeCfg" $scannerV4DBVolumeCfg }} +{{ $_ := set $._rox "_scannerV4Volume" $scannerV4DBVolumeHumanReadable }} + +{{ end }} diff --git a/4.5.2/central-services/templates/_scanner_init.tpl b/4.5.2/central-services/templates/_scanner_init.tpl new file mode 100644 index 0000000..75fbe95 --- /dev/null +++ b/4.5.2/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.5.2/central-services/templates/_set_install_method.tpl b/4.5.2/central-services/templates/_set_install_method.tpl new file mode 100644 index 0000000..9475774 --- /dev/null +++ b/4.5.2/central-services/templates/_set_install_method.tpl @@ -0,0 +1,13 @@ +{{/* + srox.setInstallMethod $ + + Sets $.env.installMethod to one of: "operator", "helm", "manifest". +*/}} + +{{ define "srox.setInstallMethod" }} +{{ $ := index . 0 }} + + +{{ $_ := set $._rox.env "installMethod" "helm" }} + +{{ end }} diff --git a/4.5.2/central-services/templates/_storage_classes.tpl b/4.5.2/central-services/templates/_storage_classes.tpl new file mode 100644 index 0000000..9183999 --- /dev/null +++ b/4.5.2/central-services/templates/_storage_classes.tpl @@ -0,0 +1,36 @@ +{{/* + srox.getStorageClasses $ + + This function attempts to retrieve information about all available StorageClasses on the + cluster and write it to + + $._rox.env.storageClasses.all: A dict mapping storage class names to dicts containing + relevant properties of the storage class. + + $._rox.env.storageClasses.default: Either nil or a string containing the name of the + default StorageClass. + */}} +{{- define "srox.getStorageClasses" -}} + + {{- $ := index . 0 -}} + {{- $storageClasses := dict -}} + {{- $defaultStorageClass := "" -}} + + {{- $lookupResult := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupResult "storage.k8s.io/v1" "StorageClass" "" "") -}} + {{- range $sc := get ($lookupResult.result | default dict) "items" | default list -}} + {{- $storageClassName := $sc.metadata.name -}} + {{- $annotations := $sc.metadata.annotations | default dict -}} + {{- $isDefault := index $annotations "storageclass.kubernetes.io/is-default-class" | default false -}} + {{- $_ := set $storageClasses $storageClassName (dict "isDefault" $isDefault) -}} + {{- if and $isDefault (not $defaultStorageClass) -}} + {{- $defaultStorageClass = $storageClassName -}} + {{- end -}} + {{- end -}} + + {{ $_ := set $._rox.env.storageClasses "all" $storageClasses }} + {{- if ne $defaultStorageClass "" -}} + {{- $_ := set $._rox.env.storageClasses "default" $defaultStorageClass -}} + {{- end -}} + +{{- end -}} diff --git a/4.5.2/central-services/values-private.yaml.example b/4.5.2/central-services/values-private.yaml.example new file mode 100644 index 0000000..8576ca8 --- /dev/null +++ b/4.5.2/central-services/values-private.yaml.example @@ -0,0 +1,224 @@ +# 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 Scanner 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----- +# +# # Secret configuration options for the Scanner V4 deployment. +# scannerV4: +# indexer: +# # Internal "scanner-v4-indexer..svc" service TLS certificate for the Scanner V4 indexer 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----- +# +# matcher: +# # Internal "scanner-v4-matcher..svc" service TLS certificate for the Scanner V4 matcher 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----- +# +# db: +# # The password to be used for authenticating database access. If this setting is omitted, a password will be +# # automatically generated upon initial deployment and the existing password will be used upon upgrades. +# password: +# value: +# +# # Internal "scanner-v4-db..svc" service TLS certificate for the Scanner V4 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----- diff --git a/4.5.2/central-services/values-public.yaml.example b/4.5.2/central-services/values-public.yaml.example new file mode 100644 index 0000000..89e1e26 --- /dev/null +++ b/4.5.2/central-services/values-public.yaml.example @@ -0,0 +1,772 @@ +# 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 `quay.io/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 `quay.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 +# +# # Public configuration options for Scanner V4. +# scannerV4: +# +# # If this is set to false, Scanner V4 will be enabled and deployed. +# # Note that currently Scanner V4 cannot be used as the only scanner component. +# # Instead it must be currently deployed side-by-side with StackRox Scanner (scanner.disable=false). +# # If it is set to true, no other setting in this section will have any effect. +# disable: true +# +# # Scanner V4 consists of three components: indexer, matcher and db. +# +# # Configuration for the indexer component: +# indexer: +# # The log level for the indexer deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # 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-v4-indexer +# 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 +# +# # Default number of indexer replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 3 +# +# # Settings related to autoscaling the indexer deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any 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 indexer deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "3Gi" +# cpu: "2000m" +# +# # Configuration for the matcher component: +# matcher: +# # The log level for the matcher deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce matcher to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # 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-v4-matcher +# 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: DoesNotExists +# +# # Default number of matcher replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 2 +# +# # Settings related to autoscaling the matcher deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any 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: 3 +# +# # Resource settings for the matcher deployment. +# resources: +# requests: +# memory: "4Gi" +# cpu: "1000m" +# limits: +# memory: "5Gi" +# cpu: "2000m" +# +# # Configuration for the DB component: +# db: +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # Scanner V4 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 +# +# # Resource settings for the DB deployment. +# resources: +# requests: +# cpu: "200m" +# memory: "2Gi" +# limits: +# cpu: "2000m" +# memory: "4Gi" +# +# # Configure DB password. If `generate` is true, a new password will be +# # generated. If it is false, a valid password is expected in `value`. +# password: +# generate: null +# value: null +# +# # Configure persistence backend for the DB. +# persistence: +# persistentVolumeClaim: +# claimName: "scanner-v4-db" +# size: "50Gi" +# +# # 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.5.2/central-services/values.yaml b/4.5.2/central-services/values.yaml new file mode 100644 index 0000000..5ed407e --- /dev/null +++ b/4.5.2/central-services/values.yaml @@ -0,0 +1,578 @@ +## 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: quay.io/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: true + storage: + endpoint: "https://console.redhat.com/connections/api" + 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 +# +## Configuration options relating to Scanner V4. +#scannerV4: +# +# # If this is set to false, Scanner V4 will be enabled and deployed. +# # If it is set to true, no other setting in this section will have any effect. +# disable: true +# +# image: +# registry: null +# name: scanner-v4 +# tag: 4.5.2 +# fullRef: null +# +# indexer: +# # The log level for the indexer deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: null +# +# # If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: null +# +# # If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# podAntiAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 100 +# podAffinityTerm: +# labelSelector: +# matchLabels: +# app: scanner-v4-indexer +# 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 +# +# # Default number of indexer replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 3 +# +# # Settings related to autoscaling the indexer deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any effect. +# disable: false +# minReplicas: 2 +# maxReplicas: 5 +# +# # Resource settings for the indexer deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "3Gi" +# cpu: "2000m" +# +# # Settings for the internal service-to-service TLS certificate used by indexer. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# matcher: +# # The log level for the matcher deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce matcher to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: null +# +# # If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: null +# +# # If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# podAntiAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 100 +# podAffinityTerm: +# labelSelector: +# matchLabels: +# app: scanner-v4-matcher +# 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 +# +# # Default number of matcher replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 2 +# # Settings related to autoscaling the matcher deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any effect. +# disable: false +# minReplicas: 2 +# maxReplicas: 3 +# +# # Resource settings for the matcher deployment. +# resources: +# requests: +# memory: "4Gi" +# cpu: "1000m" +# limits: +# memory: "5Gi" +# cpu: "2000m" +# +# # Settings for the internal service-to-service TLS certificate used by matcher. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# db: +# image: +# registry: null +# name: scanner-v4-db +# tag: 4.5.2 +# fullRef: null +# +# # Resource settings for the DB deployment. +# resources: +# requests: +# cpu: "200m" +# memory: "2Gi" +# limits: +# cpu: "2000m" +# memory: "4Gi" +# +# # Configure DB password. If `generate` is true, a new password will be +# # generated. If it is false, a valid password is expected in `value`. +# password: +# generate: null +# value: null +# +# # Configure persistence backend for the DB. +# # By default a PVC is used. Unless a Storage Class is specified +# # a default Storage Class is expected. +# persistence: +# hostPath: null +# persistentVolumeClaim: +# claimName: "scanner-v4-db" +# size: "50Gi" +# createClaim: true +# storageClass: null +# none: null +# +# nodeSelector: null +# +# # Settings for the internal service-to-service TLS certificate used by the DB. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# postgresConfig: "@config-templates/scanner-v4-db/postgresql.conf|config-templates/scanner-v4-db/postgresql.conf.default" +# hbaConfig: "@config-templates/scanner-v4-db/pg_hba.conf|config-templates/scanner-v4-db/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 +# +# +## 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.5.2/secured-cluster-services/.helmignore b/4.5.2/secured-cluster-services/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/Chart.yaml b/4.5.2/secured-cluster-services/Chart.yaml new file mode 100644 index 0000000..4ce7a5c --- /dev/null +++ b/4.5.2/secured-cluster-services/Chart.yaml @@ -0,0 +1,8 @@ +apiVersion: v2 +name: stackrox-secured-cluster-services +icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png +description: Helm Chart for StackRox Secured Clusters +type: application + +version: 400.5.2 +appVersion: 4.5.2 diff --git a/4.5.2/secured-cluster-services/README.md b/4.5.2/secured-cluster-services/README.md new file mode 100644 index 0000000..9864bdf --- /dev/null +++ b/4.5.2/secured-cluster-services/README.md @@ -0,0 +1,474 @@ +# 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. Optionally StackRox Scanner can be deployed, either alone or together +with the new Scanner V4. + +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://raw.githubusercontent.com/stackrox/helm-charts/main/opensource/. +To use StackRox Helm charts, run the following command: +```sh +helm repo add stackrox https://raw.githubusercontent.com/stackrox/helm-charts/main/opensource/ +``` +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 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 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 + ``` + +#### 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. + +Furthermore, the files `values-scanner.yaml.example`, `values-public-scanner-v4.yaml.example` +and `values-private-scanner-v4.yaml.example` list the most commonly used configuration options +for StackRox Scanner and Scanner V4. + +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. Must be a dictionary where both keys and values are strings. | `{}` | +|`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.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.|`quay.io/stackrox-io` | +|`image.collector.registry`| Address of the registry you are using for collector image.|`quay.io/stackrox-io` | +|`sensor.endpoint`| Address of the Sensor endpoint including port number. No trailing slash.|`sensor.stackrox.svc:443` | +|`collector.forceCollectionMethod`|Deprecated. This value has no effect. |`false` | +|`collector.collectionMethod`|Either `CORE_BPF`, or `NO_COLLECTION`. |`CORE_BPF` | +|`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`| Deprecated. Slim and regular Collector images are identical.|`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) | +|`collector.priorityClassName` | Name of a cluster's PriorityClass object to assign to Collector pods. | `null` (no PriorityClass assignment) | +|`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. | `true` | +|`scannerV4.disable`| Enable Scanner V4. StackRox Scanner must be enabled as well (`scanner.disable=false``). | `true` | +### Default resources + +Each of the baseline container's default resource settings are defined in the +`internal/defaults/40-resources.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/40-resources.yaml` | +|:----------------|:---------------------------------------------| +|Sensor |`sensor.resources` | +|Collector |`collector.resources` | +|Compliance |`collector.complianceResources` | +|NodeInventory |`collector.nodeScanningResources` | +|Admission Control|`admissionControl.resources` | + +Furthermore, default resource settings for StackRox Scanner and Scanner V4 can be +found in the files `internal/defaults/70-scanner.yaml` and `internal/defaults/70-scanner-v4.yaml`. + +### 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.5.2/secured-cluster-services/assets/Red_Hat-Hat_icon.png b/4.5.2/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.5.2/secured-cluster-services/assets/StackRox_icon.png b/4.5.2/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.5.2/secured-cluster-services/config-templates/scanner-v4-db/pg_hba.conf.default b/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/pg_hba.conf.default new file mode 100644 index 0000000..650f2fe --- /dev/null +++ b/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/pg_hba.conf.default @@ -0,0 +1,23 @@ +# 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 reject +host replication all 127.0.0.1/32 reject +host replication all ::1/128 reject + +### 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.5.2/secured-cluster-services/config-templates/scanner-v4-db/postgresql.conf.default b/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/postgresql.conf.default new file mode 100644 index 0000000..63ed892 --- /dev/null +++ b/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/postgresql.conf.default @@ -0,0 +1,75 @@ +#------------------------------------------------------------------------------ +# FILE LOCATIONS +#------------------------------------------------------------------------------ + +hba_file = '/etc/stackrox.d/config/pg_hba.conf' + +#------------------------------------------------------------------------------ +# CONNECTIONS AND AUTHENTICATION +#------------------------------------------------------------------------------ + +# - Connection Settings - + +listen_addresses = '*' +max_connections = 500 + +# - Authentication - + +password_encryption = 'scram-sha-256' + +# - SSL - + +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' + +#------------------------------------------------------------------------------ +# RESOURCE USAGE (except WAL) +#------------------------------------------------------------------------------ + +# - Memory - + +# Keep this in sync with the shared-memory volume in the +# templates/02-scanner-v4-07-db-deployment.yaml +shared_buffers = 750MB +work_mem = 16MB +maintenance_work_mem = 128MB +dynamic_shared_memory_type = posix + +#------------------------------------------------------------------------------ +# WRITE-AHEAD LOG +#------------------------------------------------------------------------------ + +# - Checkpoints - + +max_wal_size = 3GB +min_wal_size = 80MB + +#------------------------------------------------------------------------------ +# REPORTING AND LOGGING +#------------------------------------------------------------------------------ + +# - What to Log - + +log_timezone = 'Etc/UTC' + +#------------------------------------------------------------------------------ +# CLIENT CONNECTION DEFAULTS +#------------------------------------------------------------------------------ + +# - Locale and Formatting - + +datestyle = 'iso, mdy' +timezone = 'Etc/UTC' + +lc_messages = 'en_US.utf8' +lc_monetary = 'en_US.utf8' +lc_numeric = 'en_US.utf8' +lc_time = 'en_US.utf8' + +default_text_search_config = 'pg_catalog.english' + +# - Shared Library Preloading - + +shared_preload_libraries = 'pg_stat_statements' diff --git a/4.5.2/secured-cluster-services/config-templates/scanner-v4/indexer-config.yaml.tpl b/4.5.2/secured-cluster-services/config-templates/scanner-v4/indexer-config.yaml.tpl new file mode 100644 index 0000000..c5d28fc --- /dev/null +++ b/4.5.2/secured-cluster-services/config-templates/scanner-v4/indexer-config.yaml.tpl @@ -0,0 +1,47 @@ +{{- /* + This is the configuration file template for the Scanner v4 Indexer. + 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 v4 Indexer. +stackrox_services: true +indexer: + enable: true + database: + conn_string: > + host=scanner-v4-db.{{ .Release.Namespace }}.svc + port=5432 + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + user=postgres + sslmode=verify-full +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.statementTimeoutMs) }} + statement_timeout={{._rox.scannerV4.db.source.statementTimeoutMs}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.minConns) }} + pool_min_conns={{._rox.scannerV4.db.source.minConns}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.maxConns) }} + pool_max_conns={{._rox.scannerV4.db.source.maxConns}} +{{- end }} + client_encoding=UTF8 + password_file: /run/secrets/stackrox.io/secrets/password + get_layer_timeout: 1m + {{- if ._rox.env.centralServices }} + repository_to_cpe_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?file=repo2cpe + name_to_repos_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?file=name2repos + {{- else }} + repository_to_cpe_url: https://sensor.{{ .Release.Namespace }}.svc/scanner/definitions?file=repo2cpe + name_to_repos_url: https://sensor.{{ .Release.Namespace }}.svc/scanner/definitions?file=name2repos + {{- end }} + repository_to_cpe_file: /run/mappings/repository-to-cpe.json + name_to_repos_file: /run/mappings/container-name-repos-map.json +matcher: + enable: false +log_level: "{{ ._rox.scannerV4.indexer.logLevel }}" +grpc_listen_addr: 0.0.0.0:8443 +http_listen_addr: 0.0.0.0:9443 +proxy: + config_dir: /run/secrets/stackrox.io/proxy-config + config_file: config.yaml diff --git a/4.5.2/secured-cluster-services/config-templates/scanner-v4/matcher-config.yaml.tpl b/4.5.2/secured-cluster-services/config-templates/scanner-v4/matcher-config.yaml.tpl new file mode 100644 index 0000000..4414553 --- /dev/null +++ b/4.5.2/secured-cluster-services/config-templates/scanner-v4/matcher-config.yaml.tpl @@ -0,0 +1,39 @@ +{{- /* + This is the configuration file template for the Scanner v4 Matcher. + 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 v4 Matcher. +stackrox_services: true +indexer: + enable: false +matcher: + enable: true + database: + conn_string: > + host=scanner-v4-db.{{ .Release.Namespace }}.svc + port=5432 + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + user=postgres + sslmode=verify-full +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.statementTimeoutMs) }} + statement_timeout={{._rox.scannerV4.db.source.statementTimeoutMs}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.minConns) }} + pool_min_conns={{._rox.scannerV4.db.source.minConns}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.maxConns) }} + pool_max_conns={{._rox.scannerV4.db.source.maxConns}} +{{- end }} + client_encoding=UTF8 + password_file: /run/secrets/stackrox.io/secrets/password + vulnerabilities_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?version=ROX_VERSION + indexer_addr: scanner-v4-indexer.{{ .Release.Namespace }}.svc:8443 +log_level: "{{ ._rox.scannerV4.matcher.logLevel }}" +grpc_listen_addr: 0.0.0.0:8443 +http_listen_addr: 0.0.0.0:9443 +proxy: + config_dir: /run/secrets/stackrox.io/proxy-config + config_file: config.yaml diff --git a/4.5.2/secured-cluster-services/config-templates/scanner/config.yaml.tpl b/4.5.2/secured-cluster-services/config-templates/scanner/config.yaml.tpl new file mode 100644 index 0000000..5efc0b9 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/internal/annotations/helm-hook_secret.yaml b/4.5.2/secured-cluster-services/internal/annotations/helm-hook_secret.yaml new file mode 100644 index 0000000..68eea0c --- /dev/null +++ b/4.5.2/secured-cluster-services/internal/annotations/helm-hook_secret.yaml @@ -0,0 +1,2 @@ +helm.sh/hook: pre-install,pre-upgrade +helm.sh/resource-policy: keep diff --git a/4.5.2/secured-cluster-services/internal/annotations/helm-hook_storage.yaml b/4.5.2/secured-cluster-services/internal/annotations/helm-hook_storage.yaml new file mode 100644 index 0000000..7376533 --- /dev/null +++ b/4.5.2/secured-cluster-services/internal/annotations/helm-hook_storage.yaml @@ -0,0 +1,3 @@ +helm.sh/hook: pre-install,pre-upgrade +helm.sh/resource-policy: keep +helm.sh/hook-delete-policy: never diff --git a/4.5.2/secured-cluster-services/internal/cluster-config.yaml.tpl b/4.5.2/secured-cluster-services/internal/cluster-config.yaml.tpl new file mode 100644 index 0000000..a85ddd7 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/internal/compatibility-translation.yaml b/4.5.2/secured-cluster-services/internal/compatibility-translation.yaml new file mode 100644 index 0000000..4e33afc --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/internal/config-shape.yaml b/4.5.2/secured-cluster-services/internal/config-shape.yaml new file mode 100644 index 0000000..4a29271 --- /dev/null +++ b/4.5.2/secured-cluster-services/internal/config-shape.yaml @@ -0,0 +1,198 @@ +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 + scannerV4: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string +env: + openshift: null # bool | int + istio: null # bool + storageClasses: + all: {} # dict + default: null # string + pvcs: + names: null # [string] +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] + hostAliases: null # [dict] + priorityClassName: null # string + 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] + hostAliases: null # [dict] + priorityClassName: null # string +collector: + forceCollectionMethod: null # bool + 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 + priorityClassName: null # string + hostAliases: null # [dict] + disableSELinuxOptions: null # bool + seLinuxOptionsType: null # string + containerd: + enabled: null # bool + crio: + enabled: null # bool + runtime_config: + enabled: null # bool +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 + scanner-v4-indexer: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner-v4-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: + namespaceOverride: null # bool + useLookup: null # bool + fileOverrides: {} # dict + configFingerprintOverride: null # string + apiServer: + version: null # string + overrideAPIResources: null # [string] + extraAPIResources: null # [string] +network: + enableNetworkPolicies: null # bool +system: + enablePodSecurityPolicies: null # bool diff --git a/4.5.2/secured-cluster-services/internal/defaults/00-bootstrap.yaml b/4.5.2/secured-cluster-services/internal/defaults/00-bootstrap.yaml new file mode 100644 index 0000000..846ca57 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/internal/defaults/10-env.yaml b/4.5.2/secured-cluster-services/internal/defaults/10-env.yaml new file mode 100644 index 0000000..48605ae --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/internal/defaults/20-tls-files.yaml b/4.5.2/secured-cluster-services/internal/defaults/20-tls-files.yaml new file mode 100644 index 0000000..6eb6408 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/internal/defaults/30-base-config.yaml b/4.5.2/secured-cluster-services/internal/defaults/30-base-config.yaml new file mode 100644 index 0000000..4919efe --- /dev/null +++ b/4.5.2/secured-cluster-services/internal/defaults/30-base-config.yaml @@ -0,0 +1,120 @@ +# 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: 10 + 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: "CORE_BPF" + disableTaintTolerations: false + nodescanningEndpoint: "127.0.0.1:8444" + tolerations: + - operator: "Exists" + +auditLogs: + disableCollection: {{ ne ._rox.env.openshift 4 }} + +network: + enableNetworkPolicies: true + +enableOpenShiftMonitoring: false +--- +sensor: + exposeMonitoring: {{ ._rox.exposeMonitoring }} +collector: + exposeMonitoring: {{ ._rox.exposeMonitoring }} +admissionControl: + exposeMonitoring: {{ ._rox.exposeMonitoring }} diff --git a/4.5.2/secured-cluster-services/internal/defaults/40-resources.yaml b/4.5.2/secured-cluster-services/internal/defaults/40-resources.yaml new file mode 100644 index 0000000..4dd0c19 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/internal/defaults/50-images.yaml b/4.5.2/secured-cluster-services/internal/defaults/50-images.yaml new file mode 100644 index 0000000..0b955bb --- /dev/null +++ b/4.5.2/secured-cluster-services/internal/defaults/50-images.yaml @@ -0,0 +1,124 @@ +# This file contains the default image (registry + name + tag) settings) for all StackRox Secured Cluster +# Services. + +# Initialize default meta values +image: + registry: quay.io/stackrox-io + main: + name: main + pullPolicy: IfNotPresent + collector: + name: collector + slimName: collector-slim + scanner: + name: scanner-slim + tag: 4.5.2 + scannerDb: + name: scanner-db-slim + tag: 4.5.2 + scannerV4: + name: scanner-v4 + tag: 4.5.2 + scannerV4DB: + name: scanner-v4-db + tag: 4.5.2 +--- +# 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 }} + scannerV4: + registry: {{ ._rox.image.registry }} + scannerV4DB: + 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 "quay.io/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 "/" }} + scannerV4: + repository: {{ list ._rox.image.scannerV4.registry ._rox.image.scannerV4.name | compact | join "/" }} + scannerV4DB: + repository: {{ list ._rox.image.scannerV4DB.registry ._rox.image.scannerV4DB.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.5.2 + 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.5.2" + pullPolicy: IfNotPresent + {{- else }} + tag: "4.5.2" + 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 }}" + scannerV4: + fullRef: "{{ printf "%s:%s" ._rox.image.scannerV4.repository ._rox.image.scannerV4.tag }}" + scannerV4DB: + fullRef: "{{ printf "%s:%s" ._rox.image.scannerV4DB.repository ._rox.image.scannerV4DB.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.5.2/secured-cluster-services/internal/defaults/70-scanner-v4.yaml b/4.5.2/secured-cluster-services/internal/defaults/70-scanner-v4.yaml new file mode 100644 index 0000000..afbf0a9 --- /dev/null +++ b/4.5.2/secured-cluster-services/internal/defaults/70-scanner-v4.yaml @@ -0,0 +1,105 @@ + +scannerV4: + + disable: true + indexer: + disable: false + replicas: 2 + logLevel: INFO + metricsPort: 9090 + autoscaling: + disable: false + minReplicas: 2 + maxReplicas: 5 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: + app: scanner-v4-indexer + 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: "3Gi" + cpu: "2000m" + db: + postgresConfig: "@config-templates/scanner-v4-db/postgresql.conf|config-templates/scanner-v4-db/postgresql.conf.default" + hbaConfig: "@config-templates/scanner-v4-db/pg_hba.conf|config-templates/scanner-v4-db/pg_hba.conf.default" + source: + minConns: 10 + maxConns: 80 + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Scanner V4 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 + resources: + requests: + cpu: "200m" + memory: "2Gi" + limits: + cpu: "2000m" + memory: "4Gi" + exposeMonitoring: {{ ._rox.exposeMonitoring }} + +scannerV4DBPVCDefaults: + claimName: "scanner-v4-db" + size: "10Gi" + createClaim: true diff --git a/4.5.2/secured-cluster-services/internal/defaults/70-scanner.yaml b/4.5.2/secured-cluster-services/internal/defaults/70-scanner.yaml new file mode 100644 index 0000000..2d4d5f4 --- /dev/null +++ b/4.5.2/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: "512Mi" + + slimImage: + name: "" + tag: "" + fullRef: "" + repository: "" + + slimDBImage: + name: "" + tag: "" + fullRef: "" + repository: "" diff --git a/4.5.2/secured-cluster-services/internal/defaults/whats-this.md b/4.5.2/secured-cluster-services/internal/defaults/whats-this.md new file mode 100644 index 0000000..d58c8de --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/internal/expandables.yaml b/4.5.2/secured-cluster-services/internal/expandables.yaml new file mode 100644 index 0000000..fc280fc --- /dev/null +++ b/4.5.2/secured-cluster-services/internal/expandables.yaml @@ -0,0 +1,61 @@ +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 +scannerV4: + indexer: + nodeSelector: true + resources: true + serviceTLS: + cert: true + key: true + db: + postgresConfig: true + hbaConfig: true + password: + value: true + nodeSelector: true + resources: true + serviceTLS: + cert: true + key: true diff --git a/4.5.2/secured-cluster-services/internal/scanner-config-shape.yaml b/4.5.2/secured-cluster-services/internal/scanner-config-shape.yaml new file mode 100644 index 0000000..1a5d26f --- /dev/null +++ b/4.5.2/secured-cluster-services/internal/scanner-config-shape.yaml @@ -0,0 +1,44 @@ +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] + hostAliases: null # [dict] + dbHostAliases: null # [dict] + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + affinity: null # dict + priorityClassName: null # string + dbPriorityClassName: null # string + 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.5.2/secured-cluster-services/internal/scanner-v4-config-shape.yaml b/4.5.2/secured-cluster-services/internal/scanner-v4-config-shape.yaml new file mode 100644 index 0000000..a705b53 --- /dev/null +++ b/4.5.2/secured-cluster-services/internal/scanner-v4-config-shape.yaml @@ -0,0 +1,79 @@ +scannerV4: + disable: null # bool + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + indexer: + disable: null # bool + metricsPort: null # int + logLevel: null # string + replicas: null # int + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + matcher: + metricsPort: null # int + logLevel: null # string + replicas: null # int + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + db: + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + source: + minConns: null # int + maxConns: null # int + statementTimeoutMs: null # int + configOverride: null # string + password: + value: null # string + generate: null # bool + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + postgresConfig: null # string + hbaConfig: null # string + 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] + exposeMonitoring: null # bool diff --git a/4.5.2/secured-cluster-services/scripts/fetch-secrets.sh b/4.5.2/secured-cluster-services/scripts/fetch-secrets.sh new file mode 100755 index 0000000..850a227 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl b/4.5.2/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl new file mode 100644 index 0000000..b5a13c2 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl b/4.5.2/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl new file mode 100644 index 0000000..72bb452 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/sensor-chart-upgrade.md b/4.5.2/secured-cluster-services/sensor-chart-upgrade.md new file mode 100644 index 0000000..6402a78 --- /dev/null +++ b/4.5.2/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://raw.githubusercontent.com/stackrox/helm-charts/main/opensource/ 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.5.2/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml b/4.5.2/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml new file mode 100644 index 0000000..596b54a --- /dev/null +++ b/4.5.2/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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_secret" $annotations) -}} + {{- include "srox.annotations" (list . "secret" "secured-cluster-services-collector" $annotations) | nindent 4 }} +data: + .dockerconfigjson: {{ dict "auths" ._rox.collectorImagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/00-injected-ca-bundle.yaml b/4.5.2/secured-cluster-services/templates/00-injected-ca-bundle.yaml new file mode 100644 index 0000000..3289c2a --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/00-main-image-pull-secrets.yaml b/4.5.2/secured-cluster-services/templates/00-main-image-pull-secrets.yaml new file mode 100644 index 0000000..c033f7d --- /dev/null +++ b/4.5.2/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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_secret" $annotations) -}} + {{- include "srox.annotations" (list . "secret" "secured-cluster-services-main" $annotations) | nindent 4 }} +data: + .dockerconfigjson: {{ dict "auths" ._rox.mainImagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/00-storage-class.yaml b/4.5.2/secured-cluster-services/templates/00-storage-class.yaml new file mode 100644 index 0000000..ed5c3a0 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/00-storage-class.yaml @@ -0,0 +1,26 @@ +{{- include "srox.init" . -}} + + +{{- $name := "stackrox-gke-ssd" -}} +{{- if has $name ._rox._state.referencedStorageClasses }} + {{- $lookupOut := dict -}} + {{- $globalName := include "srox.globalResourceName" (list . $name) -}} + {{- $_ := include "srox.safeLookup" (list . $lookupOut "storage.k8s.io/v1" "StorageClass" "" $globalName) -}} + {{- if and (not $lookupOut.result) (or .Release.IsInstall $lookupOut.reliable) (not ._rox.meta.noCreateStorageClass) }} + +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ $globalName }} + labels: + {{- include "srox.labels" (list . "storageclass" $name) | nindent 4 }} + annotations: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "storageclass" $name $annotations) | nindent 4 }} +provisioner: kubernetes.io/gce-pd +parameters: + type: pd-ssd + + {{- end }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml new file mode 100644 index 0000000..a27c602 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-01-psps.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-01-psps.yaml new file mode 100644 index 0000000..23b398c --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-01-security.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-01-security.yaml new file mode 100644 index 0000000..05ff6f1 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-01-security.yaml @@ -0,0 +1,45 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable }} + +{{- if ._rox.env.openshift }} +--- +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: + - nonroot-v2 + 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.5.2/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml new file mode 100644 index 0000000..c6c0bc1 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml new file mode 100644 index 0000000..4ed16c7 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-05-network-policy.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-05-network-policy.yaml new file mode 100644 index 0000000..a61b59e --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-05-network-policy.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies -}} +{{- 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 + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP + 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 }} +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-06-deployment.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-06-deployment.yaml new file mode 100644 index 0000000..6bbe53c --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-06-deployment.yaml @@ -0,0 +1,318 @@ +{{- 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scanner._nodeSelector }} + nodeSelector: + {{- ._rox.scanner._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.tolerations }} + tolerations: + {{- toYaml ._rox.scanner.tolerations | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.hostAliases }} + hostAliases: {{ toYaml ._rox.scanner.hostAliases | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scanner.affinity | nindent 8 }} + {{- if ._rox.scanner.priorityClassName }} + priorityClassName: {{ ._rox.scanner.priorityClassName }} + {{- end }} + 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: ROX_MEMLIMIT + 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 + {{- if eq ._rox.scanner.mode "slim" }} + secretName: additional-ca-sensor + {{- else }} + secretName: additional-ca + {{- end }} + - 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scanner._dbNodeSelector }} + nodeSelector: + {{- ._rox.scanner._dbNodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.dbHostAliases }} + hostAliases: {{ toYaml ._rox.scanner.dbHostAliases | 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 + {{- if ._rox.scanner.dbPriorityClassName }} + priorityClassName: {{ ._rox.scanner.dbPriorityClassName }} + {{- end }} + 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.5.2/secured-cluster-services/templates/02-scanner-07-service.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-07-service.yaml new file mode 100644 index 0000000..2f65b15 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-08-hpa.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-08-hpa.yaml new file mode 100644 index 0000000..c7af476 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-v4-00-serviceaccount.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-00-serviceaccount.yaml new file mode 100644 index 0000000..91e4c8e --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-00-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} +{{- if (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: scanner-v4 + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "scanner-v4") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "scanner-v4") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-psps.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-psps.yaml new file mode 100644 index 0000000..14e38b4 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-psps.yaml @@ -0,0 +1,72 @@ +{{- include "srox.init" . -}} +{{- if and (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-scanner-v4-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-scanner-v4-psp") | nindent 4 }} +rules: +- apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4") }} + verbs: + - use + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-scanner-v4-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-scanner-v4-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-scanner-v4-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4-psp") }} +subjects: +- kind: ServiceAccount + name: scanner-v4 + namespace: {{ .Release.Namespace }} + +--- + +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-scanner-v4") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-scanner-v4") | 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.5.2/secured-cluster-services/templates/02-scanner-v4-01-security.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-security.yaml new file mode 100644 index 0000000..d76329c --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-security.yaml @@ -0,0 +1,51 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled }} + {{- if ._rox.env.openshift }} + {{- if eq ._rox.env.openshift 3 }} + {{ include "srox.warn" (list . "On OpenShift 3.x no SecurityContextConstraint will be configured for Scanner V4.") }} + {{- else }} + {{/* Use a default SCC that ships with OpenShift 4.x. + We only need to create a Role and a RoleBinding for + associating the SCC with the Scanner V4 deployment. */}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-scanner-v4-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-scanner-v4-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-scanner-v4-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - nonroot-v2 + verbs: + - use + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: scanner-v4-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "scanner-v4-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "scanner-v4-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-scanner-v4-scc +subjects: +- kind: ServiceAccount + name: scanner-v4 + namespace: {{ .Release.Namespace }} + {{- end }} + {{- end }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-02-db-password-secret.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-02-db-password-secret.yaml new file mode 100644 index 0000000..a382d3e --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-02-db-password-secret.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} +{{- /* The (...) below safe-guard against nil pointer evaluations for Helm versions built with Go < 1.18. */}} +{{- if and ._rox.scannerV4._dbEnabled (not (kindIs "invalid" (._rox.scannerV4.db._password).value)) }} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.scannerV4.db._password.value | nindent 4 }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-db-config.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-db-config.yaml new file mode 100644 index 0000000..439cfe8 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-db-config.yaml @@ -0,0 +1,17 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-db-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-db-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-db-config") | nindent 4 }} +data: + postgresql.conf: | + {{- ._rox.scannerV4.db._postgresConfig | nindent 4 }} + pg_hba.conf: | + {{- ._rox.scannerV4.db._hbaConfig | nindent 4 }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-indexer-config.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-indexer-config.yaml new file mode 100644 index 0000000..26705b8 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-indexer-config.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-indexer-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-indexer-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-indexer-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner-v4/indexer-config.yaml.tpl") . | nindent 4 }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-db-network-policy.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-db-network-policy.yaml new file mode 100644 index 0000000..875aba8 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-db-network-policy.yaml @@ -0,0 +1,39 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-db") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-db + ingress: +{{- if ._rox.scannerV4._indexerEnabled }} + - from: + - podSelector: + matchLabels: + app: scanner-v4-indexer + ports: + - port: 5432 + protocol: TCP +{{- end }} +{{- if ._rox.scannerV4._matcherEnabled }} + - from: + - podSelector: + matchLabels: + app: scanner-v4-matcher + ports: + - port: 5432 + protocol: TCP + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-indexer-network-policy.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-indexer-network-policy.yaml new file mode 100644 index 0000000..460801a --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-indexer-network-policy.yaml @@ -0,0 +1,90 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-indexer + ingress: + {{- if ._rox.env.centralServices }} + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8443 + protocol: TCP + - from: + - podSelector: + matchLabels: + app: scanner-v4-matcher + ports: + - port: 8443 + protocol: TCP + {{- end }} + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8443 + protocol: TCP + policyTypes: + - Ingress + +{{- if ._rox.scannerV4.exposeMonitoring }} +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: {{ ._rox.scannerV4.indexer.metricsPort }} + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-indexer + policyTypes: + - Ingress +{{- end }} +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer-monitoring-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-indexer + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-06-db-pvc.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-06-db-pvc.yaml new file mode 100644 index 0000000..8b27634 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-06-db-pvc.yaml @@ -0,0 +1,66 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.scannerV4._dbEnabled }} + +{{- if ._rox.scannerV4.db.persistence._pvcCfg }} +{{- $pvcCfg := ._rox.scannerV4.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 }} +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: + # this is used for backwards compatibility for operator if there are PVCs without annotation + # owned by the operator it will assume they belong to the deprecated central-db + {{- $labels := dict "target.pvc.stackrox.io" "scanner-v4-db" -}} + {{- include "srox.labels" (list . "persistentvolumeclaim" "scanner-v4-db" $labels) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolumeclaim" "scanner-v4-db") | nindent 4 }} +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} + +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-db-deployment.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-db-deployment.yaml new file mode 100644 index 0000000..953cb1c --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-db-deployment.yaml @@ -0,0 +1,142 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-db + {{- include "srox.labels" (list . "deployment" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-db + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-db") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "5432" + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-db") | nindent 8 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scannerV4.db._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.db._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.db.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.db.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.db.affinity | nindent 8 }} + {{- if ._rox.scannerV4.db.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.db.hostAliases | nindent 8 }} + {{- end }} + serviceAccountName: scanner-v4 + terminationGracePeriodSeconds: 120 + initContainers: + - name: init-db + image: {{ ._rox.scannerV4.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + - name: POSTGRES_HOST_AUTH_METHOD + value: "scram-sha-256" + - name: POSTGRES_PASSWORD_FILE + value: "/run/secrets/stackrox.io/secrets/password" +{{- if ._rox.env.centralServices }} + - name: SCANNER_DB_INIT_BUNDLE_ENABLED + value: "true" +{{- end }} + command: + - init-entrypoint.sh + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: scanner-v4-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + resources: + {{- ._rox.scannerV4.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + containers: + - name: db + image: {{ ._rox.scannerV4.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + - name: POSTGRES_HOST_AUTH_METHOD + value: "scram-sha-256" + {{- include "srox.envVars" (list . "deployment" "scanner-v4-db" "db") | nindent 8 }} + ports: + - name: tcp-postgresql + containerPort: 5432 + 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.scannerV4.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: config-volume + mountPath: /etc/stackrox.d/config/ + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + - name: shared-memory + mountPath: /dev/shm + securityContext: + fsGroup: 70 + volumes: + - name: disk + {{- toYaml ._rox.scannerV4.db.persistence._volumeCfg | nindent 8 }} + - name: config-volume + configMap: + name: {{ default "scanner-v4-db-config" ._rox.scannerV4.db.configOverride }} + - name: scanner-db-tls-volume + secret: + secretName: scanner-v4-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-templates/scanner-v4-db/postgresql.conf.default */}} + sizeLimit: 750Mi + - name: scanner-v4-db-password + secret: + secretName: scanner-v4-db-password +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-indexer-deployment.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-indexer-deployment.yaml new file mode 100644 index 0000000..2be0860 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-indexer-deployment.yaml @@ -0,0 +1,174 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-indexer + {{- include "srox.labels" (list . "deployment" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-indexer") | nindent 4 }} +spec: + replicas: {{ ._rox.scannerV4.indexer.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-indexer + strategy: + type: RollingUpdate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-indexer + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-indexer") | nindent 8 }} + annotations: + {{- $annotations := dict "traffic.sidecar.istio.io/excludeInboundPorts" "8443" -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "nonroot-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-indexer" $annotations) | nindent 8 }} + spec: + {{- if ._rox.scannerV4.indexer._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.indexer._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.indexer.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.indexer.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.indexer.affinity | nindent 8 }} + {{- if ._rox.scannerV4.indexer.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.indexer.hostAliases | nindent 8 }} + {{- end }} + containers: + - name: indexer + image: {{ ._rox.scannerV4.indexer.image.fullRef | quote }} + env: + - name: ROX_MEMLIMIT + 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 }} + - name: ROX_METRICS_PORT + value: ":{{- ._rox.scannerV4.indexer.metricsPort -}}" + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + - name: ROX_SECURE_METRICS_PORT + value: ":9091" + {{- end }} + {{- include "srox.envVars" (list . "deployment" "scanner-v4-indexer" "indexer") | nindent 8 }} + resources: + {{- ._rox.scannerV4.indexer._resources | nindent 10 }} + command: + - entrypoint.sh + - --conf=/etc/scanner/config.yaml + ports: + - name: grpc + containerPort: 8443 + {{ if ._rox.scannerV4.exposeMonitoring -}} + - name: monitoring + containerPort: {{ ._rox.scannerV4.indexer.metricsPort }} + {{- end}} + {{- if ._rox.monitoring.openshift.enabled }} + - containerPort: 9091 + name: monitoring-tls + {{- end }} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsNonRoot: true + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /health/readiness + port: 9443 + periodSeconds: 5 + timeoutSeconds: 1 + volumeMounts: + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: etc-ssl-volume + mountPath: /etc/ssl + - name: etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: config-volume + mountPath: /etc/scanner + readOnly: true + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: tmp-volume + mountPath: /tmp + - name: db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner-v4 + volumes: + - name: additional-ca-volume + secret: + optional: true + {{- if ._rox.env.centralServices }} + secretName: additional-ca + {{- else }} + secretName: additional-ca-sensor + {{- end }} + - name: etc-ssl-volume + emptyDir: {} + - name: etc-pki-volume + emptyDir: {} + - name: tls-volume + secret: + secretName: scanner-v4-indexer-tls + - name: config-volume + configMap: + name: scanner-v4-indexer-config + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: tmp-volume + emptyDir: {} + - name: db-password + secret: + secretName: scanner-v4-db-password + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: scanner-v4-indexer-monitoring-tls + {{- end }} + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-db-service.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-db-service.yaml new file mode 100644 index 0000000..f36bf4d --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-db-service.yaml @@ -0,0 +1,43 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-db") | nindent 4 }} +spec: + type: ClusterIP + ports: + - name: tcp-db + port: 5432 + targetPort: 5432 + selector: + app: scanner-v4-db + +{{- if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-db-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-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-v4-db-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-db.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 5432 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-indexer-service.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-indexer-service.yaml new file mode 100644 index 0000000..7b3457b --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-indexer-service.yaml @@ -0,0 +1,55 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-indexer") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: scanner-v4-indexer-monitoring-tls + {{- end }} +spec: + selector: + app: scanner-v4-indexer + clusterIP: None + ports: + - name: grpc-scanner-v4-indexer + port: 8443 + targetPort: grpc + {{- if ._rox.scannerV4.exposeMonitoring }} + - name: monitoring + port: {{ ._rox.scannerV4.indexer.metricsPort }} + targetPort: monitoring + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: indexer-monitoring-tls + port: 9091 + targetPort: monitoring-tls + {{- end }} + +{{- if ._rox.env.istio }} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-indexer-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-indexer-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-v4-indexer-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-indexer.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8443 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/02-scanner-v4-09-indexer-hpa.yaml b/4.5.2/secured-cluster-services/templates/02-scanner-v4-09-indexer-hpa.yaml new file mode 100644 index 0000000..91e4832 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/02-scanner-v4-09-indexer-hpa.yaml @@ -0,0 +1,20 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled (not ._rox.scannerV4.indexer.autoscaling.disable) }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner-v4-indexer") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scannerV4.indexer.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scannerV4.indexer.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner-v4-indexer + targetCPUUtilizationPercentage: 150 +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/99-shared-openshift-monitoring.yaml b/4.5.2/secured-cluster-services/templates/99-shared-openshift-monitoring.yaml new file mode 100644 index 0000000..2035970 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/99-shared-openshift-monitoring.yaml @@ -0,0 +1,65 @@ +{{- include "srox.init" . -}} +{{- if ._rox.monitoring.openshift.enabled -}} + {{- if (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: "scanner-v4-monitor-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "servicemonitor" (print "scanner-v4-monitor-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "servicemonitor" (print "scanner-v4-monitor-" .Release.Namespace)) | nindent 4 }} +spec: + endpoints: + {{- if ._rox.scannerV4._indexerEnabled }} + - interval: 30s + path: metrics + port: indexer-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: "scanner-v4-indexer.{{ .Release.Namespace }}.svc" + {{- end }} + {{- if ._rox.scannerV4._matcherEnabled }} + - interval: 30s + path: metrics + port: matcher-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: "scanner-v4-matcher.{{ .Release.Namespace }}.svc" + {{- end }} + selector: + matchLabels: + app.kubernetes.io/component: scanner-v4 + namespaceSelector: + matchNames: + - "{{ .Release.Namespace }}" +--- +{{/* TODO(ROX-22188): Switch to a ClusterRoleBinding to avoid leaking to + kube-system namespace. */ -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "rhacs-scanner-v4-auth-reader-{{ .Release.Namespace }}" + namespace: kube-system + labels: + {{- include "srox.labels" (list . "rolebinding" (print "rhacs-scanner-v4-auth-reader-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" (print "rhacs-scanner-v4-auth-reader-" .Release.Namespace)) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: scanner-v4 + namespace: "{{ .Release.Namespace }}" + {{- end }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/NOTES.txt b/4.5.2/secured-cluster-services/templates/NOTES.txt new file mode 100644 index 0000000..e000c0f --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/NOTES.txt @@ -0,0 +1,44 @@ +{{- $_ := 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 }} + Scanner V4: {{ if ._rox._scannerV4Enabled -}} enabled {{- else -}} disabled {{- end }} +{{- if and ._rox._scannerV4Enabled ._rox._scannerV4Volume }} + Scanner V4 DB Volume: {{ ._rox._scannerV4Volume }} +{{- end }} + +{{ 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.5.2/secured-cluster-services/templates/_compatibility.tpl b/4.5.2/secured-cluster-services/templates/_compatibility.tpl new file mode 100644 index 0000000..c83ab2d --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_crypto.tpl b/4.5.2/secured-cluster-services/templates/_crypto.tpl new file mode 100644 index 0000000..4ac1fac --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_crypto.tpl @@ -0,0 +1,247 @@ +{{/* + 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 }} + {{ $msg := list }} + {{ $msg = append $msg (printf "Tried to generate certificate for %s, but no CA certificate is available." $spec.CN) }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "Providing the CA is required when certificates for new components need to be issued. This can happen, for instance, when enabling a new component such as Scanner V4 using 'helm upgrade'." }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "If the CA was generated by the Helm chart during initial installation, you need to retrieve these auto-generated values from the cluster and provide them to the 'helm upgrade' command. A command for retrieving the auto-generated values was included in the post-installation notes of the central-services Helm chart." }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "If the CA was generated outside of the Helm chart and provided during the installation of the central-services chart, then the same must be done when executing 'helm upgrade'. This can be achieved conveniently by specifying the '--reuse-values' flag to 'helm upgrade'." }} + {{ include "srox.fail" (join "\n" $msg) }} + {{ 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.5.2/secured-cluster-services/templates/_defaults.tpl b/4.5.2/secured-cluster-services/templates/_defaults.tpl new file mode 100644 index 0000000..2e9bdd2 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_defaults.tpl @@ -0,0 +1,58 @@ +{{/* + 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 }} + +{{/* + srox.ensureCentralEndpointContainsPort . + + Appends a default port to the configured central endpoint based on a very simply heuristic. + Specifically, it only checks if the provided endpoint contains a prefix "https://" and + the part after that prefix does not contain a double colon. + This heuristic is kept simple on purpose and does not correctly add the default ports in + case the host part is an IPv6 address. +*/}} +{{ define "srox.ensureCentralEndpointContainsPort" }} + {{ $ := . }} + + {{ $endpoint := $._rox.centralEndpoint }} + {{ if hasPrefix "https://" $endpoint }} + {{ $endpoint = trimPrefix "https://" $endpoint }} + {{ if not (contains ":" $endpoint) }} + {{ include "srox.note" (list $ (printf "Specified centralEndpoint %s does not contain a port, assuming port 443. If this is incorrect please specify the correct port." $._rox.centralEndpoint)) }} + {{ $_ := set $._rox "centralEndpoint" (printf "%s:443" $._rox.centralEndpoint) }} + {{ end }} + {{ end }} + +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/_dict.tpl b/4.5.2/secured-cluster-services/templates/_dict.tpl new file mode 100644 index 0000000..bf14a6d --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_expand.tpl b/4.5.2/secured-cluster-services/templates/_expand.tpl new file mode 100644 index 0000000..9ed2531 --- /dev/null +++ b/4.5.2/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 assumed 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._expandSingle $ $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.5.2/secured-cluster-services/templates/_format.tpl b/4.5.2/secured-cluster-services/templates/_format.tpl new file mode 100644 index 0000000..745fe47 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_helpers.tpl b/4.5.2/secured-cluster-services/templates/_helpers.tpl new file mode 100644 index 0000000..69e5316 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_helpers.tpl @@ -0,0 +1,94 @@ +{{/* + 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 -}} + +{{- define "srox.checkVersionRequirements" -}} + {{- $minHelmVersion := "3.9.0" -}} + {{- $ := . -}} + + {{- $helmVersion := "" -}} + {{- if and (not (kindIs "invalid" $.Capabilities.HelmVersion)) $.Capabilities.HelmVersion -}} + {{- $helmVersion = $.Capabilities.HelmVersion.Version -}} + {{- end -}} + + {{- if empty $helmVersion -}} + {{- $msg := printf "Failed to retrieve Helm version. Please make sure you are running Helm >= v%s." $minHelmVersion -}} + {{- if $._rox.allowUnsupportedHelmVersion -}} + {{- include "srox.warn" (list $ $msg) -}} + {{- else -}} + {{- include "srox.fail" $msg -}} + {{- end -}} + {{- else if semverCompare (printf "< %s" $minHelmVersion) $helmVersion -}} + {{- $msg := printf "Helm version requirements not satisfied. Your Helm %s is too old. Please update to Helm >= v%s." $helmVersion $minHelmVersion -}} + {{- if $._rox.allowUnsupportedHelmVersion -}} + {{- include "srox.warn" (list $ $msg) -}} + {{- else -}} + {{- include "srox.fail" $msg -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/4.5.2/secured-cluster-services/templates/_image-pull-secrets.tpl b/4.5.2/secured-cluster-services/templates/_image-pull-secrets.tpl new file mode 100644 index 0000000..e758a70 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_image-pull-secrets.tpl @@ -0,0 +1,105 @@ +{{/* + srox.configureImagePullSecrets $ $cfgName $imagePullSecrets $secretResourceName $defaultSecretNames $namespace + + Configures image pull secrets. + + Note: This function must be called late in srox.init, as we rely on "srox.configureImage" to collect the + set of all referenced images first. + + This function enriches $imagePullSecrets based on the exposed configuration parameters to contain: + + 1. Optionally (i.e. only if $imagePullSecrets contains a username), a `_dockerAuths` field, containing a map + from registry URLs to settings that contain login credentials. + The map contains registries for all images passed so far to srox.configureImage invocations. + + 2. A `_names` field, containing a list of Kubernetes secret names. The chart templates then use this field + to populate imagePullSecrets lists in ServiceAccount objects. + + The list contains the following secrets: + + - Secrets referenced via $imagePullSecrets.useExisting (unconditonally). + - Image pull secrets associated with the default service account (unless + $imagePullSecrets.useFromDefaultServiceAccount was set to false by the user). + - $secretResourceName, i.e. the secret optionally created by the chart templates. This name will be included + in the list either if username/password is provided (i.e. whe the chart ensures presence of the secret) OR + if the resource already exists in the namespace (for backward compatibility with versions 4.3 or earlier). + - $defaultSecretNames, only if the corresponding secrets already exist in the namespace (again, for backward + compatibility). + + Additionally, this function fails execution if the list resulting from first three bullet points + combined is empty. + +*/}} + +{{ 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 }} + +{{ if $imagePullSecrets._username }} + {{/* When username is present, existence of $secretResourceName will be assured by the templates; add to the list. */}} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretResourceName }} + + {{ $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 }} + +{{ 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 }} + +{{/* For backward compatibility, include those secrets which already exist. + In manifest installation mode, include them unconditionally, for lack of a better way. +*/}} +{{ range $secretName := append $defaultSecretNames $secretResourceName }} + {{ $secret := dict }} + {{ include "srox.safeLookup" (list $ $secret "v1" "Secret" $namespace $secretName) }} + {{ if or (eq $._rox.env.installMethod "manifest") $secret.result }} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretName }} + {{ end }} +{{ end }} + +{{ $imagePullSecretNames = $imagePullSecretNames | uniq | sortAlpha }} +{{ $_ := set $imagePullSecrets "_names" $imagePullSecretNames }} + +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/_images.tpl b/4.5.2/secured-cluster-services/templates/_images.tpl new file mode 100644 index 0000000..dced29d --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_init.tpl b/4.5.2/secured-cluster-services/templates/_init.tpl new file mode 100644 index 0000000..6085070 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_init.tpl @@ -0,0 +1,330 @@ +{{/* + 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 }} +{{ $_ := set $ "_rox" $rox }} + +{{ $configShape := $.Files.Get "internal/config-shape.yaml" | fromYaml }} +{{/* Only merge scanner config shapes if kubectl output is disabled */}} + {{ $configShapeScanner := $.Files.Get "internal/scanner-config-shape.yaml" | fromYaml }} + {{ $_ = include "srox.mergeInto" (list $configShape $configShapeScanner) }} + {{/* Only merge scanner-v4 config shapes if kubectl output is disabled and feature flag is enabled */}} + {{ $configShapeScannerV4 := $.Files.Get "internal/scanner-v4-config-shape.yaml" | fromYaml }} + {{ $_ = include "srox.mergeInto" (list $configShape $configShapeScannerV4) }} + +{{ $_ = include "srox.mergeInto" (list $rox $configShape) }} +{{ $_ = set $._rox "_configShape" $configShape }} + +{{/* 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 }} +{{ $_ = set $state "generated" dict }} +{{ $_ = set $state "notes" list }} +{{ $_ = set $state "warnings" list }} +{{ $_ = set $state "referencedImages" dict }} +{{ $_ = set $state "referencedStorageClasses" list }} +{{ $_ = set $._rox "_state" $state }} + +{{- include "srox.checkVersionRequirements" $ -}} + +{{/* Sanity checks.*/}} +{{- if not (kindIs "invalid" ._rox.clusterLabels) }} + {{- if not (kindIs "map" ._rox.clusterLabels) }} + {{ include "srox.fail" (printf "type mismatch: clusterLabels is a %s, but must be a dict" (kindOf ._rox.clusterLabels)) }} + {{- end }} + {{- range $key, $val := ._rox.clusterLabels }} + {{- if not (kindIs "string" $key) }} + {{ include "srox.fail" (printf "type mismatch: clusterLabels contains the key %v of type %s, but only string keys are allowed" $key (kindOf $key)) }} + {{- end }} + {{- if not (kindIs "string" $val) }} + {{ include "srox.fail" (printf "type mismatch: clusterLabels.%v is of type %s, but only string values are allowed" $key (kindOf $val)) }} + {{- end }} + {{- end }} +{{- end }} + +{{/* + 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.setInstallMethod" (list $) }} + +{{ include "srox.applyDefaults" $ }} +{{ include "srox.ensureCentralEndpointContainsPort" $ }} + +{{ include "srox.getStorageClasses" (list $) }} +{{ include "srox.getPVCs" (list $) }} + +{{/* Expand applicable config values */}} +{{ $expandables := $.Files.Get "internal/expandables.yaml" | fromYaml }} +{{ include "srox.expandAll" (list $ $rox $expandables) }} + +{{ $_ = include "srox.loadAnnotationTemplates" $ }} + +{{/* + 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.mergeInto" (list $._rox.collectorImagePullSecrets $._rox.imagePullSecrets) }} + +{{/* 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.configureImage" (list $ ._rox.image.scannerV4) }} + +{{ include "srox.initGlobalPrefix" (list $) }} + +{{/* +The following block checks for the validity of the provided init bundle. (`helm install ... -f `) +1. Throw an error if no init bundle was provided +2. Throw an error if the wrong init-bundle format was provided (user wrongly passed an operator-formatted init-bundle to helm). We detect the presence of an operator init bundle by checking for the Kubernetes secret annotation "init-bundle.stackrox.io/name", that suggests a user has wrongly used `helm install ... -f .` +3. Warn if the user specified both init bundles, e.g. `helm install ... -f -f ` +*/}} +{{ $operatorInitBundlePresent := hasKey (._rox.metadata).annotations "init-bundle.stackrox.io/name" }} +{{ $helmInitBundleNotPresent := empty ._rox.ca._cert }} +{{- if and $operatorInitBundlePresent $helmInitBundleNotPresent }} + {{ include "srox.fail" (list . "It seems an init bundle in the operator format has been provided. Note that this bundle format is ignored by the Helm chart. Make sure to provide an init bundle for Helm chart installation.") }} +{{- else if and (not $helmInitBundleNotPresent) $operatorInitBundlePresent }} + {{ include "srox.warn" (list . "It seems an init bundle in the operator format has been provided. Note that this bundle format is ignored by the Helm chart.") }} +{{- else if $helmInitBundleNotPresent }} + {{ include "srox.fail" (list . "A CA certificate must be specified") }} +{{- end }} + +{{/* 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 }} + +{{ $imagePullSecretNames := list }} + +{{ if eq ._rox.scanner.disable false }} +{{/* + Local scanner setup. + */}} + {{ $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.scanner "disable" true }} + {{ end }} + + {{ 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) }} + + {{ $imagePullSecretNames = append $imagePullSecretNames "stackrox-scanner" }} +{{ end }} +{{/* + Local Scanner v4 Indexer setup. + */}} + +{{ $scannerV4Cfg := $._rox.scannerV4 }} + + + +{{/* Disable scanner v4 always in kubectl outputs */}} + +{{/* Copy secured-cluster-style image configuration to what the Scanner V4 configuration machinery expects. */}} +{{ $_ := set $._rox.scannerV4 "image" $._rox.image.scannerV4 }} +{{ $_ := set $._rox.scannerV4.db "image" $._rox.image.scannerV4DB }} + +{{ include "srox.scannerV4Init" (list $ $scannerV4Cfg) }} +{{ if ._rox.scannerV4._dbEnabled }} + {{ include "srox.scannerV4Volume" $ }} +{{ end }} + +{{ if ._rox.scannerV4._indexerEnabled }} + {{ $imagePullSecretNames = append $imagePullSecretNames "stackrox-scanner-v4" }} +{{ end }} + +{{ if not (empty $imagePullSecretNames) }} + {{ $imagePullSecretNames = append $imagePullSecretNames "stackrox" }} + {{/* Note: This must happen late, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} + {{ include "srox.configureImagePullSecrets" (list $ "imagePullSecrets" $._rox.imagePullSecrets "secured-cluster-services-main" $imagePullSecretNames $.Release.Namespace) }} +{{ end }} + +{{/* Setup Image Pull Secrets. + + Note: This must happen late, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} +{{ include "srox.configureImagePullSecrets" (list $ "mainImagePullSecrets" $._rox.mainImagePullSecrets "secured-cluster-services-main" (list "stackrox") $._rox._namespace) }} +{{ include "srox.configureImagePullSecrets" (list $ "collectorImagePullSecrets" $._rox.collectorImagePullSecrets "secured-cluster-services-collector" (list "stackrox" "collector-stackrox") $._rox._namespace) }} + +{{ end }} + +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/_injected-ca-bundle.tpl b/4.5.2/secured-cluster-services/templates/_injected-ca-bundle.tpl new file mode 100644 index 0000000..f831139 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_labels.tpl b/4.5.2/secured-cluster-services/templates/_labels.tpl new file mode 100644 index 0000000..f677d69 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_labels.tpl @@ -0,0 +1,31 @@ +{{/* + srox._labels $ $labels $extraLabels $objType $objName $forPod + + Writes all applicable [pod] labels (including default labels) for $objType/$objName + into $labels. Pod labels are written iff $forPod is true. + The dict $extraLabels can be used for specifying additional labels which + can be modified using `customize` entries before before they are added to $labels. + */}} +{{ define "srox._labels" }} +{{ $ := index . 0 }} +{{ $labels := index . 1 }} +{{ $extraLabels := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $forPod := index . 5 }} +{{ $_ := 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 "^.*/(\\d{2}-)?(admission-control|collector|sensor|scanner-v4)[^/]*\\.yaml" $.Template.Name "${2}" }} +{{ 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 $extraLabels $objType $objName $metadataNames) }} +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/_lookup.tpl b/4.5.2/secured-cluster-services/templates/_lookup.tpl new file mode 100644 index 0000000..17f6306 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_metadata.tpl b/4.5.2/secured-cluster-services/templates/_metadata.tpl new file mode 100644 index 0000000..e97d70d --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_metadata.tpl @@ -0,0 +1,307 @@ +{{/* + srox.labels $ $objType $objName [ $extraLabels ] + + Format labels for $objType/$objName as YAML. This takes into consideration the $extraLabels, + if provided, plus labels added using the generic `customize` configuration mechanism. + Note that provided $extraLabels can be modified by the user via `customize`. + + Note that pod resources are treated specially when it comes to customizing labels. + For enabling the user to define labels which shall only be applied to pods belonging + to a specific workload, the following rules apply for the Helm chart templates: + + - use the "srox.podLabels" template for injecting labels into pod templates and + - use the "srox.labels" template for injecting labels into all other resources. + + The user of the Helm charts may define `labels` within the `customize` structure for any + resources rendered as part of the charts. Such labels defined for workloads, e.g. a deployment, + will be injected into the deployment resource *and* will also be inherited to the pods belonging + to the workload. On the other hand, labels defined via `podLabels` are only meaningful for workload + resources and are only injected into the respective pods. + */}} +{{- define "srox.labels" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraLabels := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraLabels = default dict (index . 3) -}} + {{- end -}} + {{- $labels := dict -}} + {{- $_ := include "srox._labels" (list $ $labels $extraLabels $objType $objName false) }} + {{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.podLabels $ $objType $objName [ $extraLabels ] + + Format pod labels for $objType/$objName as YAML. This takes into consideration the $extraLabels, + if provided, plus labels added using the generic `customize` configuration mechanism. + Note that provided $extraLabels can be modified by the user via `customize`. + + See the description above for the template "srox.labels" for an explanation of the differences between + "srox.labels" and "srox.podLabels". + */}} +{{- define "srox.podLabels" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraLabels := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraLabels = default dict (index . 3) -}} + {{- end -}} + {{- $labels := dict -}} + {{- $_ := include "srox._labels" (list $ $labels $extraLabels $objType $objName true) }} + {{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.annotations $ $objType $objName [ $extraAnnotations ] + + Format annotations for $objType/$objName as YAML. This takes into consideration the $extraAnnotations, + if provided, plus annotations added using the generic `customize` configuration mechanism. + Note that provided $extraAnnotations can be modified by the user via `customize`. + + Note that pod resources are treated specially when it comes to customizing annotations. + For enabling the user to define annotations which shall only be applied to pods belonging + to a specific workload, the following rules apply for the Helm chart templates: + + - use the "srox.podAnnotations" template for injecting annotations into pod templates and + - use the "srox.annotations" template for injecting annotations into all other resources. + + The user of the Helm charts may define `annotations` within the `customize` structure for any + resources rendered as part of the charts. Such annotations defined for workloads, e.g. a deployment, + will be injected into the deployment resource *and* will also be inherited to the pods belonging + to the workload. On the other hand, annotations defined via `podAnnotations` are only meaningful + for workload resources and are only injected into the respective pods. + */}} +{{- define "srox.annotations" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraAnnotations := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraAnnotations = default dict (index . 3) -}} + {{- end -}} + {{- $annotations := dict -}} + {{- $_ := include "srox._annotations" (list $ $annotations $extraAnnotations $objType $objName false) -}} + {{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.podAnnotations $ $objType $objName [ $extraAnnotations ] + + Format pod annotations for $objType/$objName as YAML. This takes into consideration the $extraAnnotations, + if provided, plus annotations added using the generic `customize` configuration mechanism. + Note that provided $extraAnnotations can be modified by the user via `customize`. + + See the description above for the template "srox.annotations" for an explanation of the differences between + "srox.annotations" and "srox.podAnnotations". + */}} +{{- define "srox.podAnnotations" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraAnnotations := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraAnnotations = default dict (index . 3) -}} + {{- end -}} + {{- $annotations := dict -}} + {{- $_ := include "srox._annotations" (list $ $annotations $extraAnnotations $objType $objName 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 $extraAnnotations $objType $objName $forPod + + Writes all applicable [pod] annotations (including default annotations) for + $objType/$objName into $annotations. Pod labels are written iff $forPod is true. + The dict $extraAnnotations can be used for specifying additional annotations which + can be modified by the user using `customize` entries before before they are added to $annotations. + */}} +{{ define "srox._annotations" }} +{{ $ := index . 0 }} +{{ $annotations := index . 1 }} +{{ $extraAnnotations := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $forPod := index . 5 }} +{{ $_ := 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 $extraAnnotations $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 dict $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 $extraMetadata $objType $objName $metadataNames + + Writes custom key/value metadata to $metadata by consulting $extraMetadata in addition to 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 }} +{{ $extraMetadata := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $metadataNames := index . 5 }} + +{{ $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 $extraMetadata $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. */ -}} + {{- if hasPrefix "stackrox-" $name -}} + {{- printf "%s-%s" $._rox.globalPrefix (trimPrefix "stackrox-" $name) -}} + {{- else if hasPrefix "stackrox:" $name -}} + {{- printf "%s:%s" $._rox.globalPrefix (trimPrefix "stackrox:" $name) -}} + {{- else -}} + {{- include "srox.fail" (printf "Unknown naming convention for global resource %q." $name) -}} + {{- end -}} +{{- 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 -}} + +{{/* + srox.getAnnotationTemplate . $name $out + + Retrieve the annotation template with the given $name and store it in the provided $out parameter. + */}} +{{ define "srox.getAnnotationTemplate" }} + {{ $ := index . 0 }} + {{ $name := index . 1 }} + {{ $out := index . 2 }} + {{ if kindIs "invalid" $._rox._annotationTemplates }} + {{ include "srox.fail" "Annotation templates not initialized" }} + {{ end }} + {{ $annotationTemplates := get $._rox._annotationTemplates $name }} + {{ if not $annotationTemplates }} + {{ include "srox.fail" (printf "Annotation template %q does not exist in internal/annotations/" $name) }} + {{ end }} + {{ range $key, $value := $annotationTemplates }} + {{ $_ := set $out $key $value }} + {{ end }} +{{ end }} + +{{/* + srox.loadAnnotationTemplates . + + Load the annotation templates from `internal/annotations` and store them within $._rox. + The templates can later be retrieved with `srox.getAnnotationTemplate`. + */}} +{{ define "srox.loadAnnotationTemplates" }} + {{ $ := . }} + {{ if kindIs "invalid" $._rox._annotationTemplates }} + {{ $_ := set $._rox "_annotationTemplates" dict }} + {{ end }} + {{ range $fileName, $annotations := $.Files.Glob "internal/annotations/*.yaml" }} + {{ $name := trimSuffix ".yaml" (base $fileName) }} + {{ $_ := set $._rox._annotationTemplates $name ($annotations | toString | fromYaml) }} + {{ end }} +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/_openshift.tpl b/4.5.2/secured-cluster-services/templates/_openshift.tpl new file mode 100644 index 0000000..85201cb --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_psp.tpl b/4.5.2/secured-cluster-services/templates/_psp.tpl new file mode 100644 index 0000000..bffb2a0 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_pvcs.tpl b/4.5.2/secured-cluster-services/templates/_pvcs.tpl new file mode 100644 index 0000000..ad40204 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_pvcs.tpl @@ -0,0 +1,20 @@ +{{/* + srox.getPVCs $ + + This function attempts to retrieve information about all available PVCs in the + current namespace + + $._rox.env.pvcs.names: A list of PVC names. + */}} +{{- define "srox.getPVCs" -}} + + {{- $ := index . 0 -}} + {{- $pvcNames := list -}} + {{- $lookupResult := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupResult "v1" "PersistentVolumeClaim" $._rox._namespace "") -}} + {{- range $pvc := get ($lookupResult.result | default dict) "items" | default list -}} + {{- $pvcNames = append $pvcNames $pvc.metadata.name -}} + {{- end -}} + {{- $_ := set $._rox.env.pvcs "names" $pvcNames -}} + +{{- end -}} diff --git a/4.5.2/secured-cluster-services/templates/_reporting.tpl b/4.5.2/secured-cluster-services/templates/_reporting.tpl new file mode 100644 index 0000000..621e284 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_scanner-v4_init.tpl b/4.5.2/secured-cluster-services/templates/_scanner-v4_init.tpl new file mode 100644 index 0000000..323bfa4 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_scanner-v4_init.tpl @@ -0,0 +1,179 @@ +{{/* + srox.scannerV4Init . $scannerV4Config + + Initializes the Scanner v4 configuration. The scanner chart has two modes: Indexer and Matcher. + In Indexer mode, the Scanner pulls images and analyzes them to determine the base OS and installed packages + (i.e. it indexes the images). + In Matcher mode, the Scanner matches the found packages to known vulnerabilities to produce a Vulnerability Report. + Both modes require access to a PostgreSQL database. + + StackRox's Central service has two Scanner deployments: a Scanner running in Indexer mode and another + running in Matcher mode. In this context, the Helm chart can create its own certificates. + + StackRox's Secured Cluster services may deploy the Scanner in Indexer mode, only. + This would be done to access registries inaccessible to the Central cluster. + In this context, the Helm chart does not generate its own certificates. + + $scannerV4Config contains all values which are configured by the user. The structures can be viewed in the respective + config-shape. See internal/scanner-v4-config-shape.yaml. + */}} + +{{ define "srox.scannerV4Init" }} + +{{ $ := index . 0 }} +{{ $scannerV4Cfg := index . 1 }} +{{ $_ := false }} + +{{/* Sanity check. */}} +{{- if not (or (eq $.Chart.Name "stackrox-central-services") (eq $.Chart.Name "stackrox-secured-cluster-services")) -}} + {{- include "srox.fail" (printf "Unexpected Helm chart name %q." $.Chart.Name) -}} +{{- end -}} + +{{ $componentsCentralChart := dict "indexer" true "matcher" true }} +{{ $componentsSecuredClusterChart := dict "indexer" true "matcher" false }} + +{{/* These will be propagated up. */}} +{{ $components := dict "indexer" false "matcher" false }} +{{ $dbEnabled := false }} + +{{- if not $scannerV4Cfg.disable }} + {{/* Scanner V4 is switched on. */}} + + {{/* Scanner V4 component configuration depends on the chart. */}} + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{- $components = $componentsCentralChart -}} + {{- else -}} + {{- $components = $componentsSecuredClusterChart -}} + {{/* scannerV4.indexer.disable can be used to disable the deployment of indexer. + This is required for the operator use-case. */}} + {{- if $scannerV4Cfg.indexer.disable -}} + {{- $_ = set $components "indexer" false -}} + {{- end -}} + {{- end -}} + + {{/* Configure images, certificates and passwords as required. */}} + {{ if or (get $components "indexer") (get $components "matcher") }} + {{ include "srox.configureImage" (list $ $scannerV4Cfg.image) }} + {{ end }} + + {{ if get $components "indexer" }} + {{ $_ := set $scannerV4Cfg.indexer "image" $scannerV4Cfg.image }} + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{/* Only generate certificate when installing central-services. + For secured-cluster-services we don't configure certificates here, + instead they will be distributed at runtime by Sensor and Central. */}} + {{- if kindIs "invalid" $._rox.scannerV4.indexer.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-indexer-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.indexer.serviceTLS "generate" true -}} + {{- end -}} + {{- end -}} + {{- end }} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_INDEXER_SERVICE: Scanner V4 Indexer" "dnsBase" "scanner-v4-indexer" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.indexer.serviceTLS" $cryptoSpec) }} + {{- end -}} + {{ end }} + + {{ if get $components "matcher" }} + {{ $_ := set $scannerV4Cfg.matcher "image" $scannerV4Cfg.image }} + {{- if kindIs "invalid" $._rox.scannerV4.matcher.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-matcher-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.matcher.serviceTLS "generate" true -}} + {{- end -}} + {{- end }} + {{- end }} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_MATCHER_SERVICE: Scanner V4 Matcher" "dnsBase" "scanner-v4-matcher" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.matcher.serviceTLS" $cryptoSpec) }} + {{ end }} + + {{ if or (get $components "indexer") (get $components "matcher") }} + {{- if kindIs "invalid" $._rox.scannerV4.db.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-db-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.db.serviceTLS "generate" true -}} + {{- end -}} + {{- end -}} + {{- end }} + {{- if kindIs "invalid" $._rox.scannerV4.db.password.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-db-password") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.db.password "generate" true -}} + {{- end -}} + {{- end }} + + {{ include "srox.configureImage" (list $ $scannerV4Cfg.db.image) }} + {{ include "srox.configurePassword" (list $ "scannerV4.db.password") }} + + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{/* Only generate certificate when installing central-services. */}} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_DB_SERVICE: Scanner V4 DB" "dnsBase" "scanner-v4-db" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.db.serviceTLS" $cryptoSpec) }} + {{- end -}} + {{ end }} + +{{- if eq $.Chart.Name "stackrox-secured-cluster-services" -}} + {{/* Special handling for the secured-cluster-services chart in case it gets deployed + to the same namespace as central-services. */}} + {{ $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-v4-indexer from this chart and configuring sensor to use existing scanner-v4-indexer instance, if any.") }} + {{ $_ := set $components "indexer" false }} + {{ end }} +{{- end }} + +{{- end -}} {{/* if not $scannerV4Cfg.disable */}} + +{{/* Propagate information about which Scanner V4 components to deploy. */}} +{{- $_ := set $._rox "_scannerV4Enabled" (not $scannerV4Cfg.disable) -}} +{{- $_ := set $._rox.scannerV4 "_indexerEnabled" (get $components "indexer") -}} +{{- $_ := set $._rox.scannerV4 "_matcherEnabled" (get $components "matcher") -}} +{{- if or (get $components "indexer") (get $components "matcher") -}} + {{- $_ := set $._rox.scannerV4 "_dbEnabled" true -}} +{{- end -}} + +{{/* Provide some human-readable feedback regarding the Scanner V4 configuration to the user installing the Helm chart. */}} +{{- if and (get $components "indexer") (not (get $components "matcher")) -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "indexer" -}} +{{- else if and (not (get $components "indexer")) (get $components "matcher") -}} + {{/* Just here for completeness, not allowed currently. */}} + {{- $_ = set $._rox.scannerV4 "_installMode" "matcher" -}} +{{- else if and (get $components "indexer") (get $components "matcher") -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "indexer and matcher" -}} +{{- else -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "" -}} +{{- end -}} + +{{- if not $scannerV4Cfg.disable }} + {{- if eq $._rox.scannerV4._installMode "" }} + {{ include "srox.note" (list $ (printf "Scanner V4 is enabled and Scanner V4 components are already deployed.")) }} + {{- else }} + {{ include "srox.note" (list $ (printf "Scanner V4 is enabled and the following Scanner V4 components will be deployed: %s" $._rox.scannerV4._installMode)) }} + {{- end }} +{{- end }} + +{{- end -}} diff --git a/4.5.2/secured-cluster-services/templates/_scanner-v4_volume.tpl b/4.5.2/secured-cluster-services/templates/_scanner-v4_volume.tpl new file mode 100644 index 0000000..4d2a14b --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_scanner-v4_volume.tpl @@ -0,0 +1,113 @@ +{{/* + srox.scannerV4Volume $ + + Configures and initializes Scanner v4 persistence. + */}} +{{ define "srox.scannerV4Volume" }} +{{ $ := . }} +{{ $_ := set $ "_rox" $._rox }} + +{{ $scannerV4DBCfg := $._rox.scannerV4.db }} + +{{/* + Scanner v4 DB Volume config setup. + */}} +{{ $scannerV4DBVolumeCfg := dict }} +{{ $scannerV4DBVolumeHumanReadable := "" }} +{{ $pvcConfigShape := $._rox._configShape.scannerV4.db.persistence.persistentVolumeClaim }} +{{ $pvcDefaults := dict }} +{{- if eq $.Chart.Name "stackrox-central-services" -}} + {{ $pvcDefaults = $._rox._defaults.scannerV4DBPVCDefaults }} +{{- else -}} + {{ $pvcDefaults = $._rox.scannerV4DBPVCDefaults }} +{{- end -}} + +{{ $extraSettings := dict "createClaim" .Release.IsInstall }} +{{ if $._rox.env.storageClasses.default }} + {{ $_ = set $extraSettings "storageClass" $._rox.env.storageClasses.default }} +{{ end }} + +{{/* First we check that the persistence configuration provided by the user is sane in the sense that only one of the + supported backends emptyDir/hostPath/PVC is configured. */}} +{{ $persistenceBackendsConfigured := list }} +{{ if $scannerV4DBCfg.persistence.none }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured "emptyDir" }} +{{ end }} +{{ if $scannerV4DBCfg.persistence.hostPath }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured "hostPath" }} +{{ end }} +{{ if not (deepEqual $pvcConfigShape $scannerV4DBCfg.persistence.persistentVolumeClaim) }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured (printf "PVC:%v" $scannerV4DBCfg.persistence.persistentVolumeClaim) }} +{{ end }} + +{{/* Sanity checks and defaulting. */}} +{{ if empty $persistenceBackendsConfigured }} + {{/* No persistence backend configured, pick a reasonable default. */}} + {{ if or $._rox.env.storageClasses.default (eq $.Chart.Name "stackrox-central-services") }} + {{/* Either a default StorageClass has been detected or we are currently rendering central-services. + In both cases we configure a PVC as persistence backend. */}} + {{ if $._rox.env.storageClasses.default }} + {{ include "srox.note" (list $ "Default StorageClass detected, a PVC will be used for Scanner V4 DB persistence.") }} + {{ else }} + {{ include "srox.note" (list $ "A PVC will be used for Scanner V4 DB persistence.") }} + {{ end }} + {{ if has $pvcDefaults.claimName $._rox.env.pvcs.names }} + {{ $_ = set $extraSettings "createClaim" false }} + {{ else }} + {{ $_ = set $extraSettings "createClaim" true }} + {{ end }} + {{ $_ = include "srox.mergeInto" (list $scannerV4DBCfg.persistence.persistentVolumeClaim $pvcConfigShape $extraSettings $pvcDefaults) }} + {{ else }} + {{/* No default StorageClass detected, currently rendering secured-cluster-services chart. */}} + {{ if has $pvcDefaults.claimName $._rox.env.pvcs.names }} + {{ include "srox.note" (list $ (printf "A PVC named %s already exists, will keep using it for Scanner V4 DB persistence." $pvcDefaults.claimName)) }} + {{ $_ = set $extraSettings "createClaim" false }} + {{ $_ = include "srox.mergeInto" (list $scannerV4DBCfg.persistence.persistentVolumeClaim $pvcConfigShape $extraSettings $pvcDefaults) }} + {{ else }} + {{/* Fallback to emptyDir. */}} + {{ include "srox.warn" (list $ (printf "No default StorageClass detected, using emptyDir as persistence backend for Scanner V4 DB. It is highly recommended to use a PVC instead. Please check the documentation for more information on this." )) }} + {{ $_ = set $scannerV4DBCfg.persistence "none" true }} + {{ end }} + {{ end }} +{{ else if gt (len $persistenceBackendsConfigured) 1 }} + {{ include "srox.fail" (printf "Invalid persistence configuration for Scanner V4 DB: more than one persistence backend configured (%v)" $persistenceBackendsConfigured) }} +{{ end }} + + +{{/* Update $scannerV4DBVolumeCfg depending on configured persistence backend. */}} +{{ if $scannerV4DBCfg.persistence.none }} + {{ include "srox.warn" (list $ "Persistence for Scanner V4 DB is turned off (it is using an emptyDir volume). Every deletion of the StackRox Scanner V4 DB pod will cause you to lose all your data. This is STRONGLY recommended against.") }} + {{ $_ := set $scannerV4DBVolumeCfg "emptyDir" dict }} + {{ $scannerV4DBVolumeHumanReadable = "emptyDir" }} +{{ else if $scannerV4DBCfg.persistence.hostPath }} + {{ if not $scannerV4DBCfg.nodeSelector }} + {{ include "srox.warn" (list $ "A hostPath volume will be used by the Scanner V4 DB. At the same time no node selector is specified. This is unlikely to work reliably.") }} + {{ end }} + {{ $_ := set $scannerV4DBVolumeCfg "hostPath" (dict "path" $scannerV4DBCfg.persistence.hostPath) }} + {{ $scannerV4DBVolumeHumanReadable = printf "hostPath (%s)" $scannerV4DBCfg.persistence.hostPath}} +{{ else }} + {{ if kindIs "invalid" $scannerV4DBCfg.persistence.persistentVolumeClaim.storageClass }} + {{ include "srox.note" (list $ "A PVC using the default storage class will be used for the Scanner V4 DB.") }} + {{ else }} + {{ include "srox.note" (list $ (printf "A PVC using the storage class %q will be used for the Scanner V4 DB." $scannerV4DBCfg.persistence.persistentVolumeClaim.storageClass)) }} + {{ end }} + {{ $scannerV4DBPVCCfg := $scannerV4DBCfg.persistence.persistentVolumeClaim }} + {{ $_ := include "srox.mergeInto" (list $scannerV4DBPVCCfg $extraSettings $pvcDefaults) }} + {{ $_ = set $scannerV4DBVolumeCfg "persistentVolumeClaim" (dict "claimName" $scannerV4DBPVCCfg.claimName) }} + {{ if $scannerV4DBPVCCfg.createClaim }} + {{ $_ = set $scannerV4DBCfg.persistence "_pvcCfg" $scannerV4DBPVCCfg }} + {{ end }} + {{ if $scannerV4DBPVCCfg.storageClass }} + {{ $_ = set $._rox._state "referencedStorageClasses" (mustAppend $._rox._state.referencedStorageClasses $scannerV4DBPVCCfg.storageClass | uniq) }} + {{ end }} + {{ $scannerV4DBVolumeHumanReadable = printf "PVC (%s)" $scannerV4DBPVCCfg.claimName }} +{{ end }} + +{{ $allPersistenceMethods := keys $scannerV4DBVolumeCfg | sortAlpha }} +{{ if ne (len $allPersistenceMethods) 1 }} +{{ end }} + +{{ $_ = set $scannerV4DBCfg.persistence "_volumeCfg" $scannerV4DBVolumeCfg }} +{{ $_ := set $._rox "_scannerV4Volume" $scannerV4DBVolumeHumanReadable }} + +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/_scanner_init.tpl b/4.5.2/secured-cluster-services/templates/_scanner_init.tpl new file mode 100644 index 0000000..75fbe95 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/_set_install_method.tpl b/4.5.2/secured-cluster-services/templates/_set_install_method.tpl new file mode 100644 index 0000000..9475774 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_set_install_method.tpl @@ -0,0 +1,13 @@ +{{/* + srox.setInstallMethod $ + + Sets $.env.installMethod to one of: "operator", "helm", "manifest". +*/}} + +{{ define "srox.setInstallMethod" }} +{{ $ := index . 0 }} + + +{{ $_ := set $._rox.env "installMethod" "helm" }} + +{{ end }} diff --git a/4.5.2/secured-cluster-services/templates/_storage_classes.tpl b/4.5.2/secured-cluster-services/templates/_storage_classes.tpl new file mode 100644 index 0000000..9183999 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/_storage_classes.tpl @@ -0,0 +1,36 @@ +{{/* + srox.getStorageClasses $ + + This function attempts to retrieve information about all available StorageClasses on the + cluster and write it to + + $._rox.env.storageClasses.all: A dict mapping storage class names to dicts containing + relevant properties of the storage class. + + $._rox.env.storageClasses.default: Either nil or a string containing the name of the + default StorageClass. + */}} +{{- define "srox.getStorageClasses" -}} + + {{- $ := index . 0 -}} + {{- $storageClasses := dict -}} + {{- $defaultStorageClass := "" -}} + + {{- $lookupResult := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupResult "storage.k8s.io/v1" "StorageClass" "" "") -}} + {{- range $sc := get ($lookupResult.result | default dict) "items" | default list -}} + {{- $storageClassName := $sc.metadata.name -}} + {{- $annotations := $sc.metadata.annotations | default dict -}} + {{- $isDefault := index $annotations "storageclass.kubernetes.io/is-default-class" | default false -}} + {{- $_ := set $storageClasses $storageClassName (dict "isDefault" $isDefault) -}} + {{- if and $isDefault (not $defaultStorageClass) -}} + {{- $defaultStorageClass = $storageClassName -}} + {{- end -}} + {{- end -}} + + {{ $_ := set $._rox.env.storageClasses "all" $storageClasses }} + {{- if ne $defaultStorageClass "" -}} + {{- $_ := set $._rox.env.storageClasses "default" $defaultStorageClass -}} + {{- end -}} + +{{- end -}} diff --git a/4.5.2/secured-cluster-services/templates/additional-ca-sensor.yaml b/4.5.2/secured-cluster-services/templates/additional-ca-sensor.yaml new file mode 100644 index 0000000..aa1801c --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/admission-controller-netpol.yaml b/4.5.2/secured-cluster-services/templates/admission-controller-netpol.yaml new file mode 100644 index 0000000..9e99276 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/admission-controller-netpol.yaml @@ -0,0 +1,48 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies }} +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 }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/admission-controller-pod-security.yaml b/4.5.2/secured-cluster-services/templates/admission-controller-pod-security.yaml new file mode 100644 index 0000000..d4011f4 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/admission-controller-rbac.yaml b/4.5.2/secured-cluster-services/templates/admission-controller-rbac.yaml new file mode 100644 index 0000000..1e4e11e --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/admission-controller-secret.yaml b/4.5.2/secured-cluster-services/templates/admission-controller-secret.yaml new file mode 100644 index 0000000..3abcb9a --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/admission-controller.yaml b/4.5.2/secured-cluster-services/templates/admission-controller.yaml new file mode 100644 index 0000000..2a81f3f --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/admission-controller.yaml @@ -0,0 +1,256 @@ +{{- 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: + {{- $annotations := dict "traffic.sidecar.istio.io/excludeInboundPorts" "8443" -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "restricted-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "admission-control" $annotations) | 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 ._rox.admissionControl.priorityClassName }} + priorityClassName: {{ ._rox.admissionControl.priorityClassName }} + {{- end }} + {{- if ._rox.admissionControl.hostAliases }} + hostAliases: {{ toYaml ._rox.admissionControl.hostAliases | 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: ROX_MEMLIMIT + 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 + - deployments/scale + - replicasets + - replicationcontrollers + - statefulsets + - daemonsets + - cronjobs + - jobs + {{- if ._rox.env.openshift }} + - deploymentconfigs + {{- end }} + namespaceSelector: + matchExpressions: + - key: namespace.metadata.stackrox.io/name + operator: NotIn + values: + - {{ ._rox._namespace }} + - 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.5.2/secured-cluster-services/templates/cluster-config.yaml b/4.5.2/secured-cluster-services/templates/cluster-config.yaml new file mode 100644 index 0000000..20c81f6 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/collector-netpol.yaml b/4.5.2/secured-cluster-services/templates/collector-netpol.yaml new file mode 100644 index 0000000..4fbebe7 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/collector-netpol.yaml @@ -0,0 +1,46 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies }} +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 }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/collector-pod-security.yaml b/4.5.2/secured-cluster-services/templates/collector-pod-security.yaml new file mode 100644 index 0000000..d11ef4b --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/collector-rbac.yaml b/4.5.2/secured-cluster-services/templates/collector-rbac.yaml new file mode 100644 index 0000000..5d4ffd9 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/collector-scc.yaml b/4.5.2/secured-cluster-services/templates/collector-scc.yaml new file mode 100644 index 0000000..f593b22 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/collector-scc.yaml @@ -0,0 +1,49 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.env.openshift }} + +{{- 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 }} + auto-upgrade.stackrox.io/component: "sensor" + 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 }} + auto-upgrade.stackrox.io/component: "sensor" + 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.5.2/secured-cluster-services/templates/collector-secret.yaml b/4.5.2/secured-cluster-services/templates/collector-secret.yaml new file mode 100644 index 0000000..6b07ea2 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/collector.yaml b/4.5.2/secured-cluster-services/templates/collector.yaml new file mode 100644 index 0000000..a2f87b3 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/collector.yaml @@ -0,0 +1,234 @@ +{{- 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: + {{- $annotations := dict -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "privileged" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "daemonset" "collector" $annotations) | 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}} + {{- if ._rox.collector.priorityClassName }} + priorityClassName: {{ ._rox.collector.priorityClassName }} + {{- end }} + {{- if ._rox.collector.hostAliases }} + hostAliases: {{ toYaml ._rox.collector.hostAliases | 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 + {{- if eq ._rox.collector.collectionMethod "EBPF" }} + value: CORE_BPF + {{- else }} + value: {{ default "CORE_BPF" ._rox.collector.collectionMethod }} + {{- end }} + - 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: ROX_MEMLIMIT + 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 }} + securityContext: + privileged: true + 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.5.2/secured-cluster-services/templates/openshift-monitoring.yaml b/4.5.2/secured-cluster-services/templates/openshift-monitoring.yaml new file mode 100644 index 0000000..6e04968 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/openshift-monitoring.yaml @@ -0,0 +1,136 @@ +{{- 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 + +--- + +{{- /* +The ServiceMonitor is placed into the openshift-monitoring namespace to comply with the +OpenShift monitoring namespace label requirements. This is an exception to the rule +that leaking resources into system namespaces should be avoided. +*/}} +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 }}" + +--- + +{{- /* +TODO(ROX-22188): Switch to a ClusterRoleBinding to avoid leaking to kube-system 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 }}" + +--- + +{{- /* +The PrometheusRule is placed into the openshift-monitoring namespace to comply with the +OpenShift monitoring namespace label requirements. This is an exception to the rule +that leaking resources into system namespaces should be avoided. +Note that we have an exception for this resource for the SRE webhook validation for +managed OpenShift clusters. +*/}} +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.5.2/secured-cluster-services/templates/sensor-compliance-rbac.yaml b/4.5.2/secured-cluster-services/templates/sensor-compliance-rbac.yaml new file mode 100644 index 0000000..aec3ba8 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/sensor-compliance-rbac.yaml @@ -0,0 +1,36 @@ +{{- include "srox.init" . -}} + +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox:edit-compliance") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:edit-compliance") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:edit-compliance") | nindent 4 }} +rules: +- apiGroups: + - 'compliance.openshift.io' + resources: + - '*' + verbs: + - '*' +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox:manage-compliance") }} + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:manage-compliance") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:manage-compliance") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox:edit-compliance") }} + apiGroup: rbac.authorization.k8s.io diff --git a/4.5.2/secured-cluster-services/templates/sensor-netpol.yaml b/4.5.2/secured-cluster-services/templates/sensor-netpol.yaml new file mode 100644 index 0000000..9bb695a --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/sensor-netpol.yaml @@ -0,0 +1,95 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies }} +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 + {{- if ._rox.scannerV4._indexerEnabled }} + - podSelector: + matchLabels: + app: scanner-v4-indexer + {{- end }} + {{- 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 }} +{{- end }} diff --git a/4.5.2/secured-cluster-services/templates/sensor-pod-security.yaml b/4.5.2/secured-cluster-services/templates/sensor-pod-security.yaml new file mode 100644 index 0000000..e44a807 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/sensor-rbac.yaml b/4.5.2/secured-cluster-services/templates/sensor-rbac.yaml new file mode 100644 index 0000000..ea23ed6 --- /dev/null +++ b/4.5.2/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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:edit-workloads") }} + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:network-policies") }} + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:update-namespaces") }} + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:create-events") }} + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:review-tokens") }} + apiGroup: rbac.authorization.k8s.io diff --git a/4.5.2/secured-cluster-services/templates/sensor-secret.yaml b/4.5.2/secured-cluster-services/templates/sensor-secret.yaml new file mode 100644 index 0000000..848e1f2 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/templates/sensor.yaml b/4.5.2/secured-cluster-services/templates/sensor.yaml new file mode 100644 index 0000000..e1963a7 --- /dev/null +++ b/4.5.2/secured-cluster-services/templates/sensor.yaml @@ -0,0 +1,308 @@ +{{- 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: restricted-v2 + {{- end }} + spec: + {{- if ._rox.sensor._nodeSelector }} + nodeSelector: + {{- ._rox.sensor._nodeSelector | nindent 8 }} + {{- end}} + {{- if ._rox.sensor.tolerations }} + tolerations: + {{- toYaml ._rox.sensor.tolerations | nindent 8 }} + {{- end }} + {{- if ._rox.sensor.hostAliases }} + hostAliases: {{ toYaml ._rox.sensor.hostAliases | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.sensor.affinity | nindent 8 }} + {{- if ._rox.sensor.priorityClassName }} + priorityClassName: {{ ._rox.sensor.priorityClassName }} + {{- end }} + {{- 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: ROX_MEMLIMIT + 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._scannerV4Enabled }} + - name: ROX_SCANNER_V4_INDEXER_ENDPOINT + value: {{ printf "scanner-v4-indexer.%s.svc:8443" .Release.Namespace }} + - name: ROX_SCANNER_V4 + value: "true" + {{- end }} + {{- 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 + {{- if ._rox.env.openshift }} + - name: sensor-bound-sa-token + mountPath: /var/run/secrets/openshift/serviceaccount + {{- end }} + - 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: {} + {{- if ._rox.env.openshift }} + - name: sensor-bound-sa-token + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + path: token + audience: openshift + expirationSeconds: 3600 + {{- end }} + - 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 + {{- 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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_secret" $annotations) -}} + {{- include "srox.annotations" (list . "secret" "helm-effective-cluster-name" $annotations) | nindent 4 }} +stringData: + cluster-name: | + {{- ._rox.clusterName | nindent 4 }} +{{- end}} diff --git a/4.5.2/secured-cluster-services/templates/service-ca.yaml b/4.5.2/secured-cluster-services/templates/service-ca.yaml new file mode 100644 index 0000000..7c01760 --- /dev/null +++ b/4.5.2/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: | + {{- ._rox.ca._cert | nindent 4 }} diff --git a/4.5.2/secured-cluster-services/templates/upgrader-serviceaccount.yaml b/4.5.2/secured-cluster-services/templates/upgrader-serviceaccount.yaml new file mode 100644 index 0000000..05ba643 --- /dev/null +++ b/4.5.2/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: {{ include "srox.globalResourceName" (list . "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.5.2/secured-cluster-services/values-private-scanner-v4.yaml.example b/4.5.2/secured-cluster-services/values-private-scanner-v4.yaml.example new file mode 100644 index 0000000..abdc35e --- /dev/null +++ b/4.5.2/secured-cluster-services/values-private-scanner-v4.yaml.example @@ -0,0 +1,37 @@ +# # Private configuration options for Scanner V4 configured as part of the +# # secured-cluster-services Helm chart. +# +# scannerV4: +# +# # Configuration for the indexer component: +# indexer: +# # Internal "scanner-v4-indexer..svc" service TLS certificate for the Scanner V4 indexer 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---- +# +# # Configuration for the DB component: +# db: +# # The password to be used for authenticating database access. If this setting is omitted, a password will +# # be automatically generated upon initial deployment and the existing password will be used upon upgrades. +# password: +# value: +# +# # Internal "scanner-v4-db..svc" service TLS certificate for the Scanner V4 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---- diff --git a/4.5.2/secured-cluster-services/values-private.yaml.example b/4.5.2/secured-cluster-services/values-private.yaml.example new file mode 100644 index 0000000..ecdec21 --- /dev/null +++ b/4.5.2/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.5.2/secured-cluster-services/values-public-scanner-v4.yaml.example b/4.5.2/secured-cluster-services/values-public-scanner-v4.yaml.example new file mode 100644 index 0000000..4f8ba74 --- /dev/null +++ b/4.5.2/secured-cluster-services/values-public-scanner-v4.yaml.example @@ -0,0 +1,177 @@ +# # Public configuration options for Scanner V4 configured as part of the +# # secured-cluster-services Helm chart. +# # +# # Image configuration for Scanner V4. +# # For a complete example, see the `values-public.yaml.example` file. +# image: +# # Configuration of the `scannerV4` image. +# scannerV4: +# registry: null +# name: null +# tag: null +# fullRef: null +# +# # Configuration of the `scannerV4DB` image. +# scannerV4DB: +# registry: null +# name: null +# tag: null +# fullRef: null +# +# scannerV4: +# +# # If this is set to false, Scanner V4 will be enabled and deployed. +# # Note that currently Scanner V4 cannot be used as the only scanner component. +# # Instead it must be currently deployed side-by-side with StackRox Scanner (scanner.disable=false). +# # If it is set to true, no other setting in this section will have any effect. +# disable: true +# +# # Scanner V4 consists of three components: indexer, matcher and db. +# # But when deployed as part of secured-cluster-services the only components +# # which can be deployed are indexer and db. Scanner V4 matcher is only supposed to +# # run as part of central-services. +# +# # Configuration for the indexer component: +# indexer: +# # The log level for the indexer deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # 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-v4-indexer +# 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 +# +# # Default number of indexer replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 3 +# +# # Settings related to autoscaling the indexer deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any 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 indexer deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "3Gi" +# cpu: "2000m" +# +# # Configuration for the DB component: +# db: +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # Scanner V4 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 +# +# # Resource settings for the DB deployment. +# resources: +# requests: +# cpu: "200m" +# memory: "2Gi" +# limits: +# cpu: "2000m" +# memory: "4Gi" +# +# # Configures how Scanner V4 stores its persistent data. +# # You can use a persistent volume claim (the recommended default), a host path, +# # or an emptyDir volume if Scanner V4 is running on a secured cluster without default StorageClass. +#  # +# # For performance reasons it is HIGHLY RECOMMENDED to use a PVC. +# # Following values show how to apply custom configuration to a PVC: +# persistence: +# persistentVolumeClaim: +# claimName: "scanner-v4-db" +# size: "50Gi" +# storageClass: "some-storage-class-name" diff --git a/4.5.2/secured-cluster-services/values-public.yaml.example b/4.5.2/secured-cluster-services/values-public.yaml.example new file mode 100644 index 0000000..15aed12 --- /dev/null +++ b/4.5.2/secured-cluster-services/values-public.yaml.example @@ -0,0 +1,462 @@ +# 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. +## +## For example: +## +## clusterLabels: +## someKey: someStringValue +## +#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 quay.io/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: +# # - CORE_BPF +# # - NO_COLLECTION +# collectionMethod: CORE_BPF +# +# # 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 +# +# # 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.5.2/secured-cluster-services/values-scanner.yaml.example b/4.5.2/secured-cluster-services/values-scanner.yaml.example new file mode 100644 index 0000000..f7f3eb6 --- /dev/null +++ b/4.5.2/secured-cluster-services/values-scanner.yaml.example @@ -0,0 +1,92 @@ +# # NOTE: +# # The Scanner is not available in the secured clusters installed via roxctl. +# +# # 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.5.2/secured-cluster-services/values.yaml b/4.5.2/secured-cluster-services/values.yaml new file mode 100644 index 0000000..3297a22 --- /dev/null +++ b/4.5.2/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 e1baeac..a9edc35 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Latest version: 4.5.1](https://img.shields.io/badge/Latest%20version-4.5.1-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 @@ -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.5.1/ +[Latest version]: ./3.0.55.0/ diff --git a/latest b/latest index 59f21ae..8a44bb6 120000 --- a/latest +++ b/latest @@ -1 +1 @@ -./4.5.1/ \ 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 7431b61..d202100 100644 --- a/opensource/index.yaml +++ b/opensource/index.yaml @@ -1,9 +1,20 @@ apiVersion: v1 entries: stackrox-central-services: + - apiVersion: v2 + appVersion: 4.5.2 + created: "2024-09-14T00:55:06.935420911Z" + description: Helm Chart for StackRox Central Service + digest: 33419b010eb57464fc6e05ded4e93d723951807b2b176fd6baf8129c9b9d72d1 + 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.5.2.tgz + version: 400.5.2 - apiVersion: v2 appVersion: 4.5.1 - created: "2024-08-29T16:36:02.301452938Z" + created: "2024-09-14T00:55:06.932229364Z" description: Helm Chart for StackRox Central Service digest: 1fa1b6039f411f01e49d33908c577aaa4675f149e6328ea387ca47b55d35db90 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -14,7 +25,7 @@ entries: version: 400.5.1 - apiVersion: v2 appVersion: 4.5.0 - created: "2024-08-29T16:36:02.299152936Z" + created: "2024-09-14T00:55:06.929942458Z" description: Helm Chart for StackRox Central Service digest: b18204ef21bb25a7ecaeb5286b12787a08b340e961b6caad6385899f32bfcb59 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -25,7 +36,7 @@ entries: version: 400.5.0 - apiVersion: v2 appVersion: 4.4.5 - created: "2024-08-29T16:36:02.29686617Z" + created: "2024-09-14T00:55:06.927626438Z" description: Helm Chart for StackRox Central Service digest: 221f0dae4d314a832c0db3eacee113dc27af150a72159734f0b52a2c9ea529a7 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -36,7 +47,7 @@ entries: version: 400.4.5 - apiVersion: v2 appVersion: 4.4.4 - created: "2024-08-29T16:36:02.29459351Z" + created: "2024-09-14T00:55:06.925356734Z" description: Helm Chart for StackRox Central Service digest: e7ab4627bc6276a6664c7243fa9bb8f9e44326bf441b5b6591f237923f29ce92 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -47,7 +58,7 @@ entries: version: 400.4.4 - apiVersion: v2 appVersion: 4.4.3 - created: "2024-08-29T16:36:02.291627818Z" + created: "2024-09-14T00:55:06.922332098Z" description: Helm Chart for StackRox Central Service digest: 3f4613ac8468a241289e61ab6fcd6d77b7726ccec0b9cd068edd56ffdde6d3ff icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -58,7 +69,7 @@ entries: version: 400.4.3 - apiVersion: v2 appVersion: 4.4.2 - created: "2024-08-29T16:36:02.289411324Z" + created: "2024-09-14T00:55:06.920114341Z" 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 @@ -69,7 +80,7 @@ entries: version: 400.4.2 - apiVersion: v2 appVersion: 4.4.1 - created: "2024-08-29T16:36:02.287156999Z" + created: "2024-09-14T00:55:06.917840189Z" 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 @@ -80,7 +91,7 @@ entries: version: 400.4.1 - apiVersion: v2 appVersion: 4.4.0 - created: "2024-08-29T16:36:02.284275162Z" + created: "2024-09-14T00:55:06.914892779Z" 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 @@ -91,7 +102,7 @@ entries: version: 400.4.0 - apiVersion: v2 appVersion: 4.3.8 - created: "2024-08-29T16:36:02.281999487Z" + created: "2024-09-14T00:55:06.912699498Z" 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 @@ -102,7 +113,7 @@ entries: version: 400.3.8 - apiVersion: v2 appVersion: 4.3.7 - created: "2024-08-29T16:36:02.28024379Z" + created: "2024-09-14T00:55:06.91090881Z" 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 @@ -113,7 +124,7 @@ entries: version: 400.3.7 - apiVersion: v2 appVersion: 4.3.6 - created: "2024-08-29T16:36:02.278447147Z" + created: "2024-09-14T00:55:06.909145343Z" 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 @@ -124,7 +135,7 @@ entries: version: 400.3.6 - apiVersion: v2 appVersion: 4.3.5 - created: "2024-08-29T16:36:02.276677915Z" + created: "2024-09-14T00:55:06.907185478Z" 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 @@ -135,7 +146,7 @@ entries: version: 400.3.5 - apiVersion: v2 appVersion: 4.3.4 - created: "2024-08-29T16:36:02.274120925Z" + created: "2024-09-14T00:55:06.904683924Z" 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 @@ -146,7 +157,7 @@ entries: version: 400.3.4 - apiVersion: v2 appVersion: 4.3.3 - created: "2024-08-29T16:36:02.272321356Z" + created: "2024-09-14T00:55:06.902891934Z" 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 @@ -157,7 +168,7 @@ entries: version: 400.3.3 - apiVersion: v2 appVersion: 4.3.2 - created: "2024-08-29T16:36:02.270534221Z" + created: "2024-09-14T00:55:06.901132604Z" 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 @@ -168,7 +179,7 @@ entries: version: 400.3.2 - apiVersion: v2 appVersion: 4.3.1 - created: "2024-08-29T16:36:02.268775649Z" + created: "2024-09-14T00:55:06.899324724Z" 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 @@ -179,7 +190,7 @@ entries: version: 400.3.1 - apiVersion: v2 appVersion: 4.3.0 - created: "2024-08-29T16:36:02.266968486Z" + created: "2024-09-14T00:55:06.897533325Z" 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 @@ -190,7 +201,7 @@ entries: version: 400.3.0 - apiVersion: v2 appVersion: 4.2.5 - created: "2024-08-29T16:36:02.26444333Z" + created: "2024-09-14T00:55:06.895023362Z" 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 @@ -201,7 +212,7 @@ entries: version: 400.2.5 - apiVersion: v2 appVersion: 4.2.4 - created: "2024-08-29T16:36:02.262644102Z" + created: "2024-09-14T00:55:06.893266497Z" 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 @@ -212,7 +223,7 @@ entries: version: 400.2.4 - apiVersion: v2 appVersion: 4.2.3 - created: "2024-08-29T16:36:02.260892914Z" + created: "2024-09-14T00:55:06.891479726Z" 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 @@ -223,7 +234,7 @@ entries: version: 400.2.3 - apiVersion: v2 appVersion: 4.2.2 - created: "2024-08-29T16:36:02.25908524Z" + created: "2024-09-14T00:55:06.889717201Z" 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 @@ -234,7 +245,7 @@ entries: version: 400.2.2 - apiVersion: v2 appVersion: 4.2.1 - created: "2024-08-29T16:36:02.256696536Z" + created: "2024-09-14T00:55:06.887792903Z" 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 @@ -245,7 +256,7 @@ entries: version: 400.2.1 - apiVersion: v2 appVersion: 4.2.0 - created: "2024-08-29T16:36:02.254895365Z" + created: "2024-09-14T00:55:06.885260023Z" 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 @@ -256,7 +267,7 @@ entries: version: 400.2.0 - apiVersion: v2 appVersion: 4.1.6 - created: "2024-08-29T16:36:02.253139177Z" + created: "2024-09-14T00:55:06.88347759Z" 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 @@ -267,7 +278,7 @@ entries: version: 400.1.6 - apiVersion: v2 appVersion: 4.1.5 - created: "2024-08-29T16:36:02.251413327Z" + created: "2024-09-14T00:55:06.881780407Z" 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 @@ -278,7 +289,7 @@ entries: version: 400.1.5 - apiVersion: v2 appVersion: 4.1.4 - created: "2024-08-29T16:36:02.249693138Z" + created: "2024-09-14T00:55:06.880066232Z" 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 @@ -289,7 +300,7 @@ entries: version: 400.1.4 - apiVersion: v2 appVersion: 4.1.3 - created: "2024-08-29T16:36:02.24724516Z" + created: "2024-09-14T00:55:06.877605364Z" 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 @@ -300,7 +311,7 @@ entries: version: 400.1.3 - apiVersion: v2 appVersion: 4.1.2 - created: "2024-08-29T16:36:02.245424191Z" + created: "2024-09-14T00:55:06.875858047Z" 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 @@ -311,7 +322,7 @@ entries: version: 400.1.2 - apiVersion: v2 appVersion: 4.1.1 - created: "2024-08-29T16:36:02.243682521Z" + created: "2024-09-14T00:55:06.874132561Z" 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 @@ -322,7 +333,7 @@ entries: version: 400.1.1 - apiVersion: v2 appVersion: 4.1.0 - created: "2024-08-29T16:36:02.241963224Z" + created: "2024-09-14T00:55:06.872425329Z" 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 @@ -333,7 +344,7 @@ entries: version: 400.1.0 - apiVersion: v2 appVersion: 4.0.5 - created: "2024-08-29T16:36:02.239635535Z" + created: "2024-09-14T00:55:06.870292622Z" 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 @@ -344,7 +355,7 @@ entries: version: 400.0.5 - apiVersion: v2 appVersion: 4.0.4 - created: "2024-08-29T16:36:02.23758308Z" + created: "2024-09-14T00:55:06.86815791Z" 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 @@ -355,7 +366,7 @@ entries: version: 400.0.4 - apiVersion: v2 appVersion: 4.0.3 - created: "2024-08-29T16:36:02.235841341Z" + created: "2024-09-14T00:55:06.866391798Z" 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 @@ -366,7 +377,7 @@ entries: version: 400.0.3 - apiVersion: v2 appVersion: 4.0.2 - created: "2024-08-29T16:36:02.233942134Z" + created: "2024-09-14T00:55:06.864671211Z" 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 @@ -377,7 +388,7 @@ entries: version: 400.0.2 - apiVersion: v2 appVersion: 4.0.1 - created: "2024-08-29T16:36:02.232220211Z" + created: "2024-09-14T00:55:06.862873259Z" 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 @@ -388,7 +399,7 @@ entries: version: 400.0.1 - apiVersion: v2 appVersion: 4.0.0 - created: "2024-08-29T16:36:02.229685223Z" + created: "2024-09-14T00:55:06.860430639Z" 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 @@ -399,7 +410,7 @@ entries: version: 400.0.0 - apiVersion: v2 appVersion: 3.74.9 - created: "2024-08-29T16:36:02.352535587Z" + created: "2024-09-14T00:55:06.98210423Z" 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 @@ -410,7 +421,7 @@ entries: version: 74.9.0 - apiVersion: v2 appVersion: 3.74.8 - created: "2024-08-29T16:36:02.350659564Z" + created: "2024-09-14T00:55:06.980271013Z" 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 @@ -421,7 +432,7 @@ entries: version: 74.8.0 - apiVersion: v2 appVersion: 3.74.7 - created: "2024-08-29T16:36:02.348816103Z" + created: "2024-09-14T00:55:06.978394625Z" 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 @@ -432,7 +443,7 @@ entries: version: 74.7.0 - apiVersion: v2 appVersion: 3.74.6 - created: "2024-08-29T16:36:02.346904453Z" + created: "2024-09-14T00:55:06.976565384Z" 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 @@ -443,7 +454,7 @@ entries: version: 74.6.0 - apiVersion: v2 appVersion: 3.74.5 - created: "2024-08-29T16:36:02.344236865Z" + created: "2024-09-14T00:55:06.974688565Z" 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 @@ -454,7 +465,7 @@ entries: version: 74.5.0 - apiVersion: v2 appVersion: 3.74.4 - created: "2024-08-29T16:36:02.342367645Z" + created: "2024-09-14T00:55:06.972124638Z" 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 @@ -465,7 +476,7 @@ entries: version: 74.4.0 - apiVersion: v2 appVersion: 3.74.3 - created: "2024-08-29T16:36:02.340529653Z" + created: "2024-09-14T00:55:06.970267565Z" 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 @@ -476,7 +487,7 @@ entries: version: 74.3.0 - apiVersion: v2 appVersion: 3.74.2 - created: "2024-08-29T16:36:02.338652479Z" + created: "2024-09-14T00:55:06.968415743Z" 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 @@ -487,7 +498,7 @@ entries: version: 74.2.0 - apiVersion: v2 appVersion: 3.74.1 - created: "2024-08-29T16:36:02.336796594Z" + created: "2024-09-14T00:55:06.96653705Z" 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 @@ -498,7 +509,7 @@ entries: version: 74.1.0 - apiVersion: v2 appVersion: 3.74.0 - created: "2024-08-29T16:36:02.334189667Z" + created: "2024-09-14T00:55:06.964672945Z" 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 @@ -509,7 +520,7 @@ entries: version: 74.0.0 - apiVersion: v2 appVersion: 3.73.5 - created: "2024-08-29T16:36:02.331391658Z" + created: "2024-09-14T00:55:06.962106938Z" 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 @@ -520,7 +531,7 @@ entries: version: 73.5.0 - apiVersion: v2 appVersion: 3.73.4 - created: "2024-08-29T16:36:02.329560089Z" + created: "2024-09-14T00:55:06.960281304Z" 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 @@ -531,7 +542,7 @@ entries: version: 73.4.0 - apiVersion: v2 appVersion: 3.73.3 - created: "2024-08-29T16:36:02.327688213Z" + created: "2024-09-14T00:55:06.95839106Z" 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 @@ -542,7 +553,7 @@ entries: version: 73.3.0 - apiVersion: v2 appVersion: 3.73.2 - created: "2024-08-29T16:36:02.324656765Z" + created: "2024-09-14T00:55:06.956573421Z" 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 @@ -553,7 +564,7 @@ entries: version: 73.2.0 - apiVersion: v2 appVersion: 3.73.1 - created: "2024-08-29T16:36:02.320989773Z" + created: "2024-09-14T00:55:06.954693456Z" 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 @@ -564,7 +575,7 @@ entries: version: 73.1.0 - apiVersion: v2 appVersion: 3.73.0 - created: "2024-08-29T16:36:02.319133267Z" + created: "2024-09-14T00:55:06.952116781Z" 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 @@ -575,7 +586,7 @@ entries: version: 73.0.0 - apiVersion: v2 appVersion: 3.72.4 - created: "2024-08-29T16:36:02.317303531Z" + created: "2024-09-14T00:55:06.950263116Z" 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 @@ -586,7 +597,7 @@ entries: version: 72.4.0 - apiVersion: v2 appVersion: 3.72.3 - created: "2024-08-29T16:36:02.315683802Z" + created: "2024-09-14T00:55:06.948642796Z" 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 @@ -597,7 +608,7 @@ entries: version: 72.3.0 - apiVersion: v2 appVersion: 3.72.2 - created: "2024-08-29T16:36:02.31406361Z" + created: "2024-09-14T00:55:06.947011376Z" 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 @@ -608,7 +619,7 @@ entries: version: 72.2.0 - apiVersion: v2 appVersion: 3.72.1 - created: "2024-08-29T16:36:02.312211414Z" + created: "2024-09-14T00:55:06.945415402Z" 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 @@ -619,7 +630,7 @@ entries: version: 72.1.0 - apiVersion: v2 appVersion: 3.72.0 - created: "2024-08-29T16:36:02.310151645Z" + created: "2024-09-14T00:55:06.943103806Z" 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 @@ -630,7 +641,7 @@ entries: version: 72.0.0 - apiVersion: v2 appVersion: 3.71.3 - created: "2024-08-29T16:36:02.308543096Z" + created: "2024-09-14T00:55:06.941520375Z" description: Helm Chart for StackRox Central Clusters digest: df3fca54fb637426e3c895d7356b7dfb95ed64384e005919cfa8de571d48a20d icon: https://www.stackrox.com/img/logo.svg @@ -641,7 +652,7 @@ entries: version: 71.3.0 - apiVersion: v2 appVersion: 3.71.2 - created: "2024-08-29T16:36:02.306916092Z" + created: "2024-09-14T00:55:06.940015391Z" description: Helm Chart for StackRox Central Clusters digest: 7ff76bf8dc53b249ab1d9c61fd203f834777a39346e217e18862cb6b47808204 icon: https://www.stackrox.com/img/logo.svg @@ -652,7 +663,7 @@ entries: version: 71.2.0 - apiVersion: v2 appVersion: 3.71.0 - created: "2024-08-29T16:36:02.305392733Z" + created: "2024-09-14T00:55:06.938464451Z" description: Helm Chart for StackRox Central Clusters digest: 22115098ea95e326a08063c0fd5089647d729e58d6d668a9ad22841055f17498 icon: https://www.stackrox.com/img/logo.svg @@ -663,7 +674,7 @@ entries: version: 71.0.0 - apiVersion: v2 appVersion: 3.70.0 - created: "2024-08-29T16:36:02.303831974Z" + created: "2024-09-14T00:55:06.936950711Z" description: Helm Chart for StackRox Central Clusters digest: db1c6b84de673bcf72f41b21059b020ad91bd116ddb38772fc0292296e484e5f icon: https://www.stackrox.com/img/logo.svg @@ -673,9 +684,20 @@ entries: - stackrox-central-services-70.0.0.tgz version: 70.0.0 stackrox-secured-cluster-services: + - apiVersion: v2 + appVersion: 4.5.2 + created: "2024-09-14T00:55:07.053772028Z" + description: Helm Chart for StackRox Secured Clusters + digest: 8c169ecd2baf2f5732f8a691c764e3a6d4500d3dd2f5f2791a31b16e41976a14 + 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.5.2.tgz + version: 400.5.2 - apiVersion: v2 appVersion: 4.5.1 - created: "2024-08-29T16:36:02.422678519Z" + created: "2024-09-14T00:55:07.051647024Z" description: Helm Chart for StackRox Secured Clusters digest: ed57c96cb5506a1523158ec3a023f24cf62aac7e8fdf24702ec0298e061a949b icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -686,7 +708,7 @@ entries: version: 400.5.1 - apiVersion: v2 appVersion: 4.5.0 - created: "2024-08-29T16:36:02.42058128Z" + created: "2024-09-14T00:55:07.049440409Z" description: Helm Chart for StackRox Secured Clusters digest: 1b8a1a5aaacb120ffbde235eb52389359ad90e5bf5884f9f5abd1bbb52fdd5d4 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -697,7 +719,7 @@ entries: version: 400.5.0 - apiVersion: v2 appVersion: 4.4.5 - created: "2024-08-29T16:36:02.417783671Z" + created: "2024-09-14T00:55:07.046612464Z" description: Helm Chart for StackRox Secured Clusters digest: e798de08570ac9357b9a66b4d1bf04df795811554eaae0bd83bbe0efdf52d021 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -708,7 +730,7 @@ entries: version: 400.4.5 - apiVersion: v2 appVersion: 4.4.4 - created: "2024-08-29T16:36:02.415729133Z" + created: "2024-09-14T00:55:07.044598478Z" description: Helm Chart for StackRox Secured Clusters digest: 9fb92920251c4bfec60823f4ba9cbb392c3cf8bc692fe8866a110a9e76c772af icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -719,7 +741,7 @@ entries: version: 400.4.4 - apiVersion: v2 appVersion: 4.4.3 - created: "2024-08-29T16:36:02.413705041Z" + created: "2024-09-14T00:55:07.042547273Z" description: Helm Chart for StackRox Secured Clusters digest: c7d3096e19b3f4020a332030095fac159f96fa46a80baf24bd2a3022eb702ae4 icon: https://raw.githubusercontent.com/stackrox/stackrox/master/image/templates/helm/shared/assets/StackRox_icon.png @@ -730,7 +752,7 @@ entries: version: 400.4.3 - apiVersion: v2 appVersion: 4.4.2 - created: "2024-08-29T16:36:02.411651323Z" + created: "2024-09-14T00:55:07.040515013Z" 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 @@ -741,7 +763,7 @@ entries: version: 400.4.2 - apiVersion: v2 appVersion: 4.4.1 - created: "2024-08-29T16:36:02.40895191Z" + created: "2024-09-14T00:55:07.038087094Z" 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 @@ -752,7 +774,7 @@ entries: version: 400.4.1 - apiVersion: v2 appVersion: 4.4.0 - created: "2024-08-29T16:36:02.40689154Z" + created: "2024-09-14T00:55:07.035829623Z" 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 @@ -763,7 +785,7 @@ entries: version: 400.4.0 - apiVersion: v2 appVersion: 4.3.8 - created: "2024-08-29T16:36:02.404831721Z" + created: "2024-09-14T00:55:07.033787735Z" 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 @@ -774,7 +796,7 @@ entries: version: 400.3.8 - apiVersion: v2 appVersion: 4.3.7 - created: "2024-08-29T16:36:02.403106102Z" + created: "2024-09-14T00:55:07.032111661Z" 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 @@ -785,7 +807,7 @@ entries: version: 400.3.7 - apiVersion: v2 appVersion: 4.3.6 - created: "2024-08-29T16:36:02.400567889Z" + created: "2024-09-14T00:55:07.030390804Z" 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 @@ -796,7 +818,7 @@ entries: version: 400.3.6 - apiVersion: v2 appVersion: 4.3.5 - created: "2024-08-29T16:36:02.398867346Z" + created: "2024-09-14T00:55:07.028025628Z" 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 @@ -807,7 +829,7 @@ entries: version: 400.3.5 - apiVersion: v2 appVersion: 4.3.4 - created: "2024-08-29T16:36:02.397202862Z" + created: "2024-09-14T00:55:07.026330699Z" 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 @@ -818,7 +840,7 @@ entries: version: 400.3.4 - apiVersion: v2 appVersion: 4.3.3 - created: "2024-08-29T16:36:02.395467845Z" + created: "2024-09-14T00:55:07.024645178Z" 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 @@ -829,7 +851,7 @@ entries: version: 400.3.3 - apiVersion: v2 appVersion: 4.3.2 - created: "2024-08-29T16:36:02.393774286Z" + created: "2024-09-14T00:55:07.022932495Z" 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 @@ -840,7 +862,7 @@ entries: version: 400.3.2 - apiVersion: v2 appVersion: 4.3.1 - created: "2024-08-29T16:36:02.39122225Z" + created: "2024-09-14T00:55:07.020501192Z" 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 @@ -851,7 +873,7 @@ entries: version: 400.3.1 - apiVersion: v2 appVersion: 4.3.0 - created: "2024-08-29T16:36:02.389519463Z" + created: "2024-09-14T00:55:07.018774764Z" 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 @@ -862,7 +884,7 @@ entries: version: 400.3.0 - apiVersion: v2 appVersion: 4.2.5 - created: "2024-08-29T16:36:02.38780796Z" + created: "2024-09-14T00:55:07.017087499Z" 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 @@ -873,7 +895,7 @@ entries: version: 400.2.5 - apiVersion: v2 appVersion: 4.2.4 - created: "2024-08-29T16:36:02.386144889Z" + created: "2024-09-14T00:55:07.015393021Z" 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 @@ -884,7 +906,7 @@ entries: version: 400.2.4 - apiVersion: v2 appVersion: 4.2.3 - created: "2024-08-29T16:36:02.384426122Z" + created: "2024-09-14T00:55:07.013709093Z" 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 @@ -895,7 +917,7 @@ entries: version: 400.2.3 - apiVersion: v2 appVersion: 4.2.2 - created: "2024-08-29T16:36:02.382251883Z" + created: "2024-09-14T00:55:07.011540438Z" 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 @@ -906,7 +928,7 @@ entries: version: 400.2.2 - apiVersion: v2 appVersion: 4.2.1 - created: "2024-08-29T16:36:02.38029052Z" + created: "2024-09-14T00:55:07.009516735Z" 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 @@ -917,7 +939,7 @@ entries: version: 400.2.1 - apiVersion: v2 appVersion: 4.2.0 - created: "2024-08-29T16:36:02.37859124Z" + created: "2024-09-14T00:55:07.007782021Z" 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 @@ -928,7 +950,7 @@ entries: version: 400.2.0 - apiVersion: v2 appVersion: 4.1.6 - created: "2024-08-29T16:36:02.376925312Z" + created: "2024-09-14T00:55:07.006086691Z" 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 @@ -939,7 +961,7 @@ entries: version: 400.1.6 - apiVersion: v2 appVersion: 4.1.5 - created: "2024-08-29T16:36:02.375153957Z" + created: "2024-09-14T00:55:07.004376504Z" 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 @@ -950,7 +972,7 @@ entries: version: 400.1.5 - apiVersion: v2 appVersion: 4.1.4 - created: "2024-08-29T16:36:02.372788115Z" + created: "2024-09-14T00:55:07.002648192Z" 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 @@ -961,7 +983,7 @@ entries: version: 400.1.4 - apiVersion: v2 appVersion: 4.1.3 - created: "2024-08-29T16:36:02.371074929Z" + created: "2024-09-14T00:55:07.000367825Z" 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 @@ -972,7 +994,7 @@ entries: version: 400.1.3 - apiVersion: v2 appVersion: 4.1.2 - created: "2024-08-29T16:36:02.369410484Z" + created: "2024-09-14T00:55:06.998663267Z" 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 @@ -983,7 +1005,7 @@ entries: version: 400.1.2 - apiVersion: v2 appVersion: 4.1.1 - created: "2024-08-29T16:36:02.367713609Z" + created: "2024-09-14T00:55:06.99700133Z" 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 @@ -994,7 +1016,7 @@ entries: version: 400.1.1 - apiVersion: v2 appVersion: 4.1.0 - created: "2024-08-29T16:36:02.366010462Z" + created: "2024-09-14T00:55:06.995310208Z" 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 @@ -1005,7 +1027,7 @@ entries: version: 400.1.0 - apiVersion: v2 appVersion: 4.0.5 - created: "2024-08-29T16:36:02.363471726Z" + created: "2024-09-14T00:55:06.993624847Z" 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 @@ -1016,7 +1038,7 @@ entries: version: 400.0.5 - apiVersion: v2 appVersion: 4.0.4 - created: "2024-08-29T16:36:02.361775271Z" + created: "2024-09-14T00:55:06.991228039Z" 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 @@ -1027,7 +1049,7 @@ entries: version: 400.0.4 - apiVersion: v2 appVersion: 4.0.3 - created: "2024-08-29T16:36:02.360116999Z" + created: "2024-09-14T00:55:06.989575118Z" 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 @@ -1038,7 +1060,7 @@ entries: version: 400.0.3 - apiVersion: v2 appVersion: 4.0.2 - created: "2024-08-29T16:36:02.358412088Z" + created: "2024-09-14T00:55:06.98788577Z" 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 @@ -1049,7 +1071,7 @@ entries: version: 400.0.2 - apiVersion: v2 appVersion: 4.0.1 - created: "2024-08-29T16:36:02.356728277Z" + created: "2024-09-14T00:55:06.986197624Z" 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 @@ -1060,7 +1082,7 @@ entries: version: 400.0.1 - apiVersion: v2 appVersion: 4.0.0 - created: "2024-08-29T16:36:02.354514664Z" + created: "2024-09-14T00:55:06.98452132Z" 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 @@ -1071,7 +1093,7 @@ entries: version: 400.0.0 - apiVersion: v2 appVersion: 3.74.9 - created: "2024-08-29T16:36:02.467702777Z" + created: "2024-09-14T00:55:07.098460366Z" 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 @@ -1082,7 +1104,7 @@ entries: version: 74.9.0 - apiVersion: v2 appVersion: 3.74.8 - created: "2024-08-29T16:36:02.466042661Z" + created: "2024-09-14T00:55:07.096816012Z" 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 @@ -1093,7 +1115,7 @@ entries: version: 74.8.0 - apiVersion: v2 appVersion: 3.74.7 - created: "2024-08-29T16:36:02.464385249Z" + created: "2024-09-14T00:55:07.095133405Z" 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 @@ -1104,7 +1126,7 @@ entries: version: 74.7.0 - apiVersion: v2 appVersion: 3.74.6 - created: "2024-08-29T16:36:02.462037947Z" + created: "2024-09-14T00:55:07.093489532Z" 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 @@ -1115,7 +1137,7 @@ entries: version: 74.6.0 - apiVersion: v2 appVersion: 3.74.5 - created: "2024-08-29T16:36:02.460401275Z" + created: "2024-09-14T00:55:07.091804511Z" 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 @@ -1126,7 +1148,7 @@ entries: version: 74.5.0 - apiVersion: v2 appVersion: 3.74.4 - created: "2024-08-29T16:36:02.458744134Z" + created: "2024-09-14T00:55:07.089349401Z" 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 @@ -1137,7 +1159,7 @@ entries: version: 74.4.0 - apiVersion: v2 appVersion: 3.74.3 - created: "2024-08-29T16:36:02.457099057Z" + created: "2024-09-14T00:55:07.087684718Z" 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 @@ -1148,7 +1170,7 @@ entries: version: 74.3.0 - apiVersion: v2 appVersion: 3.74.2 - created: "2024-08-29T16:36:02.45542262Z" + created: "2024-09-14T00:55:07.086044932Z" 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 @@ -1159,7 +1181,7 @@ entries: version: 74.2.0 - apiVersion: v2 appVersion: 3.74.1 - created: "2024-08-29T16:36:02.453073015Z" + created: "2024-09-14T00:55:07.084401379Z" 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 @@ -1170,7 +1192,7 @@ entries: version: 74.1.0 - apiVersion: v2 appVersion: 3.74.0 - created: "2024-08-29T16:36:02.451396347Z" + created: "2024-09-14T00:55:07.08270122Z" 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 @@ -1181,7 +1203,7 @@ entries: version: 74.0.0 - apiVersion: v2 appVersion: 3.73.5 - created: "2024-08-29T16:36:02.449750649Z" + created: "2024-09-14T00:55:07.080355685Z" 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 @@ -1192,7 +1214,7 @@ entries: version: 73.5.0 - apiVersion: v2 appVersion: 3.73.4 - created: "2024-08-29T16:36:02.448106042Z" + created: "2024-09-14T00:55:07.078675123Z" 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 @@ -1203,7 +1225,7 @@ entries: version: 73.4.0 - apiVersion: v2 appVersion: 3.73.3 - created: "2024-08-29T16:36:02.446392415Z" + created: "2024-09-14T00:55:07.077034445Z" 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 @@ -1214,7 +1236,7 @@ entries: version: 73.3.0 - apiVersion: v2 appVersion: 3.73.2 - created: "2024-08-29T16:36:02.44403892Z" + created: "2024-09-14T00:55:07.07535732Z" 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 @@ -1225,7 +1247,7 @@ entries: version: 73.2.0 - apiVersion: v2 appVersion: 3.73.1 - created: "2024-08-29T16:36:02.442359097Z" + created: "2024-09-14T00:55:07.073694981Z" 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 @@ -1236,7 +1258,7 @@ entries: version: 73.1.0 - apiVersion: v2 appVersion: 3.73.0 - created: "2024-08-29T16:36:02.44070957Z" + created: "2024-09-14T00:55:07.07141032Z" 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 @@ -1247,7 +1269,7 @@ entries: version: 73.0.0 - apiVersion: v2 appVersion: 3.72.4 - created: "2024-08-29T16:36:02.439028745Z" + created: "2024-09-14T00:55:07.069769572Z" 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 @@ -1258,7 +1280,7 @@ entries: version: 72.4.0 - apiVersion: v2 appVersion: 3.72.3 - created: "2024-08-29T16:36:02.437354993Z" + created: "2024-09-14T00:55:07.068108547Z" 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 @@ -1269,7 +1291,7 @@ entries: version: 72.3.0 - apiVersion: v2 appVersion: 3.72.2 - created: "2024-08-29T16:36:02.434835975Z" + created: "2024-09-14T00:55:07.066429777Z" 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 @@ -1280,7 +1302,7 @@ entries: version: 72.2.0 - apiVersion: v2 appVersion: 3.72.1 - created: "2024-08-29T16:36:02.433191899Z" + created: "2024-09-14T00:55:07.064748925Z" 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 @@ -1291,7 +1313,7 @@ entries: version: 72.1.0 - apiVersion: v2 appVersion: 3.72.0 - created: "2024-08-29T16:36:02.431518768Z" + created: "2024-09-14T00:55:07.06242009Z" 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 @@ -1302,7 +1324,7 @@ entries: version: 72.0.0 - apiVersion: v2 appVersion: 3.71.3 - created: "2024-08-29T16:36:02.429878038Z" + created: "2024-09-14T00:55:07.06077809Z" description: Helm Chart for StackRox Secured Clusters digest: f05b85662ed91d727ea7ebea0219be5ef0d80e657d69f40b961d5166c88d6292 icon: https://www.stackrox.com/img/logo.svg @@ -1313,7 +1335,7 @@ entries: version: 71.3.0 - apiVersion: v2 appVersion: 3.71.2 - created: "2024-08-29T16:36:02.428290639Z" + created: "2024-09-14T00:55:07.05917358Z" description: Helm Chart for StackRox Secured Clusters digest: 7624e7c16f5f22aaa34ffac654606fb974813f895f312cd1fbd6c103959e9ad0 icon: https://www.stackrox.com/img/logo.svg @@ -1324,7 +1346,7 @@ entries: version: 71.2.0 - apiVersion: v2 appVersion: 3.71.0 - created: "2024-08-29T16:36:02.425930873Z" + created: "2024-09-14T00:55:07.057597553Z" description: Helm Chart for StackRox Secured Clusters digest: eb8decbde7b849b7b21357c0b2812b404b6c08f69e97d2a57478a413223f21e3 icon: https://www.stackrox.com/img/logo.svg @@ -1335,7 +1357,7 @@ entries: version: 71.0.0 - apiVersion: v2 appVersion: 3.70.0 - created: "2024-08-29T16:36:02.424360406Z" + created: "2024-09-14T00:55:07.055967986Z" description: Helm Chart for StackRox Secured Clusters digest: e6ef2cdc20620fab37e0cfd6b5a5646c83e5b1360bd0a7eddd835f5824c16c8a icon: https://www.stackrox.com/img/logo.svg @@ -1344,4 +1366,4 @@ entries: urls: - stackrox-secured-cluster-services-70.0.0.tgz version: 70.0.0 -generated: "2024-08-29T16:36:02.227616828Z" +generated: "2024-09-14T00:55:06.85853244Z" diff --git a/opensource/stackrox-central-services-400.5.2.tgz b/opensource/stackrox-central-services-400.5.2.tgz new file mode 100644 index 0000000000000000000000000000000000000000..c13ee3df35fcb132529f3d6ce26222dcc3650a32 GIT binary patch literal 90876 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

LZQOapidBVBPN>H(k2|=3;CZk=|O1Q&%E&7&` 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 literal 0 HcmV?d00001 diff --git a/opensource/stackrox-secured-cluster-services-400.5.2.tgz b/opensource/stackrox-secured-cluster-services-400.5.2.tgz new file mode 100644 index 0000000000000000000000000000000000000000..5043dddf8d578618b7ba103a11b573a56e4a05f4 GIT binary patch literal 90907 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∈gusN?75l2kI9{pJm4>tb#_;>L6nbD z=l3VC&fgrqeO=pdYxQ1a+SqVmE3IRly#M?8>B0Wd(d(1*SKpl<9tDpnsMEaOVe;+} zjZWIk-rM0CwOb%jyRxSw^BSIQCaZ!8IpRe8mTfe8v_NgOy47LNwY=5(br_R6hHtT9 zEjxJAj@3DQ_X}d6o7~ys;Sy)A?Zn;Uye)b`y!lg*Qf5$8(`dr?n~ql*nH2qs8Urb| z?j>8>rsKL#YfKym(g6|Fiq( z|NAhXd(Z#+)e^tnZ^qZxh{&2-jPDZD0ikk-2_V?7ujL`r z=^fLEkMPH;we~$_!grCHSFnEbFxdtVk6S{jmM5!w44rE1{awFEEjPd%`cmS&QNlI#H%2dJ$vx~$w{TXB@s4|V6q4q!3@2r4&M%7$%_ZSE z&iXm)1GN4`i)r_=(P@PjFEf8X+VNP52z)IesHz>kGR*W4)^c+8_7rTDu)n|oAOWvB z$m>YZJRw!hUVBYL8QVcgGufv(fQX}Ok>2g6Y{_!WgmfDhcWp{6rb%psjTpS3R@{T2 zj%CxUrWWBXnUd_3NJ;Zi7^vl>&b*uqlrH15QU9@X0^<9t!_)omjLE7Kg2zU?A>1>$ zr-MHY#do4|e?$+=>1&YsHRjq%?frD{&;;+Z_il2nf(vWP*G=XBZ~Nl{FIfO+QU0%; zt$O{>oo6q$9_9as_}pdwuVyP;N+uGVDW>T62wah>HkC)x4~)~_SuSyQ%+h_+g7Ak| zCdLktf~D9Ya!<;|4Mwwk2)vOx0}B0(@LHPqLi}mju2oCj74SO)vC>6cwE3B-?;E~m zs3pC(7Euq5fBH$%%%s3PCOjdz1iSmzv(0)y{i7-A7M~mP|LN{EN&qe5|C>9F{69O- zo;~vahxp9r|Aw(csWP7_eAtc86%+bI_-jZ8ls10{#{%~|B*MQ{ouK}7_n}J#^{2ZJ zQZ1-;oUc?c=rObyUo169epSwFdn~(heAwEm-e<=TS7k9w_&N@-k z-TNyQHHsah4OdJUg79)MNFi$Irj`=T`Fnk|n?v z$p70f8ukC5Z9mrkc$m*}_W#?<{>U$jKPS1){K(54KZK)(_Z8;3cNe|S(ffkrr@CMK z3FQo(hAy=St{xV;qFIIp#5l96g8+|_CKeBU*p2Nq+!pEo`SZp%=qEuCw%(%X^xy!= zF_uV-X(7-Rm17T|-S|@wcJwnrEYD^rCnQCZAszdRFo>(5eqmp7Rk-=xu@EewSgN1o zn84sLBK*V60eLAq(Kj14gWTQJWt;9kaA`I@;C)wT>l)=xRG{rX)S+tjU!_W0HSPlx zYMVFMUDs+er{w+=7*r2(>$33P;{IQ{1lYp&|7Z30{}-Fj9`FAL`7E~oZG3~y#ssa! zaoj@#lCdi!@R0OJCFUu@BTRE4QBE@incxUVWQw!W1lOxu^aqknY|yRHo;&(_`ktZx zhqmIaZ_Rb&nHwA8L^`mN#9Dg^v9)@abP%6g^6Z&9V)LG%7L*a2?tYa@V&Sm&TTE>6 zSbwH^Vzn)9FDdq@H8}ey);vwgG2DddcXCnmo7~mR32_U zkX;3b@9$WC#p1)QNIdXiy_1r}^}yT@yRiWuPl)6+5yy;6KS}QG>K2E5VOjCTky|xo z&j*H7SHL|~xNcqW{yiqmxYo}1mra>*FLc*FdJFBnkskGYYz4sDDk#`eX)cl5lBQ*J~y-gK0GrA;wA=1cq>T3@C@5Dx@tMMt9U<8s#uE3AQr5H)M`jwU;O+ll4B|qLn?)dMi}7a@(S}*poC2dEGZP0 zoxyLm!iJ&-IVPMS%n3UFaG+xkSSdZSGy|}!Tyr@&CLRD24S|IyCq(@=1Gmq7gd~He zDJeKffJGYh-7oC6s%N1Na!M14BAwDFR+5634X$D2cBw~ia2jE?n-C2u_jyFyM}D~T zy5t$FW#;GPw~~lT#=q4O_b_=B%>TE2ZXy4_fDH0gNKvO6Fkk-P+S=S{y#H=(J^KGV z$mfpzKW|W1^yV+PtuLE5uP%D`ue#S6=KgAo+Lie;lo_pdseK)nt~A*o86b2*qj1HI?NE3 znDB|ol>9x%2{|U5Le3Mzj9l6E_WF5U)$=-PXz8iYMP;;tnpv(k-S@Bd&-T4HHCKnO zqX5)KF;f4FnviUjyC2@4o}KUiboRsfyVqwwynodKTqGP%`eKax+s~fQ0o7G7?*_&4 zmV1>A@u(HjJOA#dqgQWVpT9oZ|L*PUwt4BAdJUREO7WcFJoVQfHdo;=gZRH#jNOmz zHN0F|H!3c@v9D9Kt6rC=5u4Wrbom-}9p&+sD{p4_A75DEth2yZdvPw*Rpx7{!g>Gd zN3MB6FIhRym)yV6rtfy#>=0u2N&IUo9R`RL3v@QJFDb!eP3~0XL z9Y6hTKdFCFFZlQ+__rPq6{B-16jC$P{|QBQo)PMg(bo2hcr)INw@|;R&u)lmR&sJS z=0uEHmhPb)f9|yl#3yc1f)&H-x#j&T>4dOSR$c$>$MON#Uwc8m5EhY1#qH7!-DRVb zlXew9yng9J2YHN@ggPM;#%CQ6Q!?EUrzvS-F@MXJE6b;m_*XA@*h+z}+@VjCB&FqK5521s zt4W0LBO!&c%jZbU@!lect2IzT_6>;QMgxzV=v6!|)tWP#zX`xf|^{u%~hgU7iVT@V>!6m^=5BNSEk;^yEr zyU!iizwHVK2(~Ww5>{$U@3%Hpw*$JBz1o7j6Qgw-uzRpv+hJ~GzP6ojW5aHPvD`en z&0lp6(QN~>qudwclq@T_jJdgDSu?8jOl-cXXI&h4rB`yR@a=r7`$ z-eO1n{{6fCzaO8xKRCUIF_WTfvC_RdKiYrSuwOTa8+Hr>-)oiM-V3pU-8t0h@&3U* zj0ZPOo!8DuN{ecn{r>p%(diF|Z_dv5j}KdHl-hjm!>_T^kaEsW4i8SxkKdm(sAmsF zd-J%KANbM#OyIIv+Gy>LFcG;H?Iyq~&_^7C!qI8CXNWpLI{@O)!)Dfk9d%iRDg+eU)>3E`3s zX#z$Ge+}E8?d+gLCVe5YCCud_YwcWI(#4&NOR8{`ycDtl<#wj^Ys_`&mjQi9mj_&M z_G#8%27K34dQA!c5tKRQ0(kH2h)XjE6sIvl!N{6$~?`; zhw2{6SA1+kD-nE| z9_#-<%;%2%|LawqzgFfpLzegI-M{o0)}F23OH5J3L!CCkX!E{Hnep1IWfapj}$XWw)dg@=em`Ci;>#dHg2#Tf6nmpmbjH}FZ>S_vq;t)Lo&5@~YQ2blfIJtpHw zE9`igHMXS#o24kim%39T5>5+UfiQYSg*pf55Y}~a_VyH_G1cC|F0CU$^Ms&N1>uB! zvH~tdb?Q+W zo$7%5Fr$qVGV*dVP>O)(Nhtl7zX^CEy*fPI|L*PU$21^!`nlEpZ-u}GLcoIif2Vo> zKi}Pb%>VHqpZoCtxSkMj&zbvLZ|VDR?6~egH&EZ~IU5j(gUWIn@Jl`d)2J!M)n7h2 zR-m!j3t_%=QSDk{<(WNn#B$Om)r@$N^yj31^Y=TqBEJ=TpT^QmFZ;1mHf` z3#(mY6KikNZF^Bmx7Ch@Xi+4D#H&x3rHlK+;e{{mGRJKf4k z$wY!Pb>pO(c{VCBdTlD_;U5^Mzq4H8?3ktdrUl_&RiYd_oC=m=htvH_n713)a(i$J zUc!~w-!rd|@hrxlt`DT@W6~Wd^v^)Nan4(9e&p)=hA;WNhoKcKH60xP^pm8SDbIUM zctUasPJmm_HXpB#Yx4iU{jG08shn`@$*(uf|FgOKypjL^`SY#E`i~FtxrY8fSGno? z%Fr6)3-5~sg*$p}dW(la!Z=|fPS|9lZf-CtVapxi^GO4%-*qoU;q}o*@i#U`7!Z-o zblHYi)Ph#;9_$r&hl{;nNS=a&qmR$h6=pzpnc{2@?Q9x#*!u4({oGTK=V;K@32rQ9 zp}&!tsg-H9iUhx*8L>WFoK1)vlTvKBdTk=Gsfd1p`vZ8X-Y^T-Pp}tjsv5OJw5~g5 z2K^+XB$pcMhRlQq>7M)0NnLQg>9-WM|=$)v(CM&E2S zvIX-2PLx0jVl=SBMx_C7#J1~$k8vV=9aur@bAnT{^hM&~d;R-^vy2Qheig%>i`Bhf zBlm@pf@`z_Tu_tup>qpYtcIX=&}|s`BuTC|zmE&54;ElTa!C{DZg5%=<=~$ru~zFq zoG`wKtqOEI-L>jjd%gF@u+1|N>01cQK7$KYy++asXvoEnJv7L=ECV`!S=}MnIptwAFIz zUbd44^}ZnaDTK(GU0i@ocP#U!A~7_?nSg}=H)-{a8^0crhx}F9PbX9;YEx7sIm^(` zWH4szQXm}@M$$bW52u)7+tKuk(^-xuG>J1v2J}8ZfV`+;+2%U@ed*?}rzDr6V+v;I z4GWXxL&g)B$x>4=?U$Z|Yi|bxyiWBkhd%5saRmLKvU8^-ysnG`$QlZqFTDEF*n-pg z-5A)MoAB!2Yv~QQQsPU3)VGL14t_Lb zS;nqtKH5|LInGC<4a6URtn>jB^aWjUT>MPs82#;A6n)GQii{n`$3*?v@4)H`^PJ`* zjo7Oa9>xv#1^&7oVuoD%E5ZpPImkMMle7zG*8$M}dH>|-@aX%!+v6V|bM^D#yW{sK zXZuHId*~mmL}NT9?ocZ|lOdc}jHqu3%)U#a!y%fn5(z?(9Al~e!BN4|Amj~m*fUT$ z(=vmqFucrHRsuR=41Wu2l?pCbToHLUQuMT z1Am{-IL?J;9;UVtTGjGmN1>>a5bfeYy4b6y%zb6t!)@5NM zAhEvJ51tny^aYA+LJA2DI}}^bQ?_5tz^bVhwbl5{5Oeia12xs7hZ;;PSf%suk$oB75hC);) ztA({XMQgYy)XurpS-tG_>VxQ6wP2vv22`RlhlD!KWpV9lQBI-Vv=;NX9N4)lKCMq< zRTi0{4V`(&5_se-O#~xFXic*J7A&teF5>v=gZ{03D^|5R^$o|P3CX1zMi#KfcHr~x*iYAAPNlalkcBU?MKO~SDqs|E8CMpZEEd9}1_;7Nc+s_~6zX$nz{=D(c3PNypETxkJ*k`ngR`rf+Hl%s6C`h8Tqq8v; zXiTz#a5OCQ1Wt#8AP`0cr&D$PT#^}L9C=wg&{|OrGMd15=>PgHdn+~wT&K!ehxX6szJ!70)mxQvjIU^-?fnX7t0ld6ep1A;*!iRfP-Av8lo4d;H*#+Cjt~w?-wdi zUS`=kqSB^Z7HR-O<(P1EA$dtIRuE!&pumfDJp@?HF4V7OG2%E?185A?s^ki1oTuQX zEF`#0z@`zzi6}FPXl_TEuoR4wN@JBI*H3UT!&O#FvkGON5^ff-T6A4IP_1lz<=4&f zpr_|gQNfAgd3pimn4nCp7cfAQ5y%^hUdN+&9noPMFoj)&<3XH6+J52Fg5}Imv~WNm z`-LW&Rb%&39bwg0kS=uyv+C$BB;#OT@VlQUv7-6oicb41&t`7vv{J9S4fP3$FUjn^ zYGHB`sq>Jty#G7l%%cbzE>ZVw}qHL@ih;NQ@41op)M|xDLZOT2&qN zZVSD4Y9L5L;6_qib^1=Q`IxCDtf1ANT>Pkr$I$Bxv7xv9F?z2^<%){>;Fg|OkXi>t zvuN##%NRi70Rx*25VsmxsUV`ajxfv;C#DWS_A&Q2%kK9I z@(hqVyM}pq4VNBQ!?=MlI@k|}1fU6%oGc+SuhZ})FOyvxv=HSOL zu(!hAP#M9)YY(;sgSmlVR5uuK;M4sh0Y*MJ(ZTw0MTeYDiD6-iPzFlOe06kMA2H3v zcUb7WBREMIw~i8#xy>gb}!OmZ?M!A%Sj?*`-kt{Gdf+c(W}R|6|>wW;=` zX$DZj3j$ChCqu;)p>x$-i`wf*l*w3|WtC>25bqj5ooju0f6!w36)Uq;n}ZV!#c^RB zow_R-5_D2zGl;fn8y;cNr((gKbA{cdqfdbuU*9Ld7+Qb0B(q4bpgO4fP_8@SqcK0- z%S>tjwaHt=jEkgV7MD$Cp$}CxO^!Wkr`kZhvB ze@}9K2?FNoz^X%46-o~j?wXM4-Ur%kij7@q)4J6y(NMLuo6!joESr)hpxB~^Ruf%> z-pDqUp8vgDPHSB;zl}(43fG6tI&glglwGB37a5iC53L#2rxut2lyLMqBNG^<6=G!+ z7>^-7BBr@0?W$AH|QO{BuJE;G$~f`Hhtfa z6s^IL6=R@!oas741AST(tl03N1f^Zt&xHnllx+> zc`a;J1EpAtb;dXphgz4bV`5>qfpSVkfqjy}vC(bvf4R#`c6=#l( zhd;eU)<&rQR6(bNDD)qRla9 zQ>w+!F;Qbvfo!n>bTuY~8r?Egeapn~&L`l+ETbL4@qcM!N4&A^Mk|$(c zgM~+bH7*VTYWWfi-yK9hsXrZ)Y+`LDPvd1~w@jPEp`CglG#Lwt_TEaym`kM#Xr~M+ zDb8xn88cS8rQk$zN~XkUlem#bL9~u%)Xi|-HZ^sO_U)gryk<rzDrzOi_=%;bs=I zr~N)Br67I17f;bJ!=UsnpzGFqS3f*_RD69RMxD=Vdc_6yDx3uDE&%PTos~2Noi*1n zYHN)pC%BTqLzdb0Zro(4tykglm*JqKS$g0!8niZezDx21#R&!tsuz6oBboJ^y&_rgd!*Ky{Av-p2NVoIB?h z`GD}Y=>&JPmg7xFttCmm@eTvG;&lzP4JD#dq_kRh!dP7u@zh7ZQK!Oc@3sYsYfe7N1zM>YIM7OU zr@CtUGWaQ2p(eaFcz|d}?+da5*ZC6>^&G`ISanxRr2c(+(Ec z8tM*8E3NN%$0l8{;=sj~ry2dSI+l=2IQ>Zw{%hxZp3=+VDbE55NowsM`|sZRRw}rZ zE+Cw!;}xu@AKXZu7!!Yhm-k#}*8v?$h$$8DstAU9H=et7&8uM14#QmY@CF64Vy>UF zM8Y^!EbDlbQc`TeiZXL{$eQcy%vr6$ps!~iygk$(tKij-<-Zfo)`22zCj;Hkn#KtD zgEN^x!`L6tCZ+L_a~(+ahA>cP%2H(Dd~YlNFZ=cv@wQ_w^ZPc?@zSRp!v*drcZ@=6A8p_ z!^f4us!(Z>yc%KYGo|d$j}bK3BnOp%m2*{H2LpH^IF6fGnUbi@;!J zm(`p^+XE@R?sp6;t3!U3%&mpV)J+X*7U1>)ELFiGnHHrWJjW9fub5}=Mei3t7wJEh z5|viZDcNipQ?})^3yj$Tt7|i42NT(QY1AGqdW}NMnJT_U;bKD6V?*-x}%&H6b_2FvLC}GOItk?_zaNN{ zs5VqoT$x$SpGF7Cw!Klnd(dzchs!zlJ>@$FE?5q-c2Lj&6nCmb2x~pI5)#caGQwGm zPRN8Axuq^%tRu#aU~YJ#Cmm|3t9}dgn)lM(E1li<$yZl68>sy&D4WjSr*05dO0+7b z$q}9q@V3%FYZ~Dk2bAiD&H>wt?wTp}CzwU?oA-{0vYD>KI+Do;1@a@rQPl;`M z0$Da&x8qsWP0Nt#p3PBYhl{K3zrqitIogoy$7vYDD(xDIsFZN zQ9_i2`>s0211!iZJ-9uDPel9#OqvGkRa?5b8d8+QA%%b&Sr!>lGI|8Lcl7^4nu&bw z57Y3+f}t!H7VsDMr~&Qg1q66(MlFA&H#4ewE)g_vE&qS(rhLr^fCcfN&o-a$)cyaT z?YwyO|9^;&&&t8T^2)lRgXX-iST+%rgSzGpz-}&F(5C(MVjb8}ju=nDu7IUt;UrH5 zV#a(%GXk8vo96^*1Y9T9|Je8j@S0UvSvcm5+V9`cjI3AxJS(yw@HArsFY?s3+W5wV znmR@yi|mvn5_kA5Ic`=2i#^IpH-Ut3jwK!Dw;cCq%y?4kZv1x%1c9_S!@ z1#h#?U(8^Ds2kXE5!fuSjue@`1SW)&Y^FGTff7!%UBx^AfD~-qe}y02Zy!53$x{M< zfsSUrEif0_{a4*aR|H+*+~zpbZ}bV_5`%dOLjz6{Hp=PmKp7y!JAX_OqaO&o*yB`* zpA*b42}haQaID=!NuFv?<0;{EIMYz69Z`(gl|W@-O^$kUvH2CYzIt3z(;=x{LA6Ro z(6Q^Pr2LQ3$B+46-|e6L`1<7I$NXaiLcR^eQes%BNP&_v#^O}7=&0(PN8zBoIWMC% z;aoMREJsh^Fga3I2LwG4Rp3BvJt5ClKt%z$_qr59M>#HD6THDWktNTyn>e_SgJ4`1 z%+O6h0?TjyKlb0fwL8?d`_7o%*g`e4S5$AGLv<~|vbMX?$Nc`(C3)?DGkH;&m0L@R>_VZxvT zvp7&%!(J+IC1AUfx^jYfLvU8r)Vf@_jH2KQpQ@__D^@YHe%@nJaw;TE6h)nCr8d!m zKb4x!lQBsyg`x_O{jJZ3gY3oW6r8{*hwPJk8yk@qI#hty$WYqb&9qG!(PF;=qo&46 zrRXFqvjRE1uNg!YJH8}^)H5JzN=3;FCUgvi2aj`-$ZQ7NxFej77* z!QwXX&4$|O zVdLFn2;cm~z$vPIMSGpDjQXTUwe}tpdm{FBcXv7gcNzA=yggq(W8vfHEB4eEwMf?O{H3Qyw-F$Eq%%fPPs`Ng>C-T3a4g>WB>wHf;t(h{ZiR8)81cTQzn*SE4_dy*CXj7&)u0;N)rY>0HoEAZjC`8*D|t)O`> z588#HuYDMR52vc(gyzPbge$^_{CfZmu_@suG*>^)nPpKesP;lIe%LvI$KsSSSQLS- zNS4KD-{6JVP-%V>f^&$lG;k2kGShVh!JNgqQY$e}Ga|ra7P`+j%9(v~>M`ac;i<@t zrxlSwZ8~V@J+whLYe9p5Y&OkIW=E=|BSAwm+1jtp0H_xJ1I~UVvkn_xmGH!jQ+vZ{ zNj{PjJL+b4%8_7|Y{nV1Cdz^Bywyy&5%}*CpIl*+AzK#a04SjoZUuW(YQ9)5(lPwQ4v5SX~m7hzP?lw?GbwEGNou2@vFXb&leMA!B# zFlcT)9ysxSv=$uQM3c1Fyk_X}=-zZ#@H{+ik^Bs`z$Ra!W~j})Y+S0>2k+d5K)UgO zZf!o+J}PS|A;keJW?|B*PSjd}hR1o%hMB_+AX-NY;VRv}l8V7c-^L(g330Da#2$$1 zIu%_;09ThE2+a1EnlHT{R_T!5>!AG)y}5a++Ear0OBe8+k?Wy^v1f9;^N7 ztHuT9k|t$_xofbZeK^$tUx&v|$Wx>3@or>P<_XL7ODWE>nF+nui|w#nw_Vm(5QNKG z0L}wa3&C?vL9j%P1F-Z9YCT_^dp=D{&VwUkTX(tRDL`MG7&^xxukJX}jK5Jsdxr`B zU3u!Me>Gk8EaUHT1}i!5wE%6nVzr&frNGX6GPN^mJ?G&`cScsUDn}Bn3Z87mvHIUp zhhXK$>Ou2$6vy#8{C#BPDmjwtXhcDYDx8nJPJLnes}mwe`Z)fSXY`Vw(}L5{Q=td4 z`i-?sRcVNaI1@7$zNe$oT#`HUq_++Uc8pg7`IL~tM!#Js$?U>**Pe_x6HKk6P-hQ= z%@L*-Amr}oUYLM{M-p^Pb$$*F(DM@4vY_x63?n6HfRa}DuEtg- zbShc`Hc@yWgDM25VuvOx5=`m}&xCmsA?Z3A>pk#XHwOgKe9A8UfB-%Lnr$ni&@{+9 zl7atj_d5B9*VW3NqZWzOx+U-=lt=5Lrr-$(d(hH5WpWep+yC|y9J^)%MBm&q@ zA<>ND35g2oGIC-k+$GliL+3E_1jNIpAUI^)$%#({nu>-@sK;^tRD&-T3$4Q2!N~w- zuk9BA-z8O=wGQ@edBO5)+ov8s_xrh){a3q;-*NuWtQ zfL1F5l$S^H7m(?G)!Kkg9A`xe6ZT*_Y2ywj5S%_T`a}h2-K1jBiV>=UdgR#4XAndh za>hVKu_GuBto>RzDHsQ*7xREBY-%fKNfszq3W3!gbUFzUXc)Gw4c|AyJ$j?Y0Yz9> z=wrihl2#HbI1vyrSes}VF<4oV3&NG$K++(BP+PD<7)Hwjm4sW-(#RmqNDdZ6eEF6! zN`%eHnOA{Mumz12cynW7wS01LI-&N%rNsWN|}>wcG@J)PsT&=$O9 zhk?Xeh>ffj?rb*X?(l>*aq}~yI}{u6J>gX^)S4e90rdbX96E&R z1y3sTrQrFN3Js_-D$LJm2Dg-BMmG9Jg7V-JOHXjIjz&!GfhOUtQlXQ^J4Hed-HfAY zGf4)U0a;i~?(Sm@MqiWc9&2B$NLa@y;Gp*S%?*3ksTbW11@AMnb)!I=U#-`kjy|xC zf&F?$VQ8ylF)1v|9pL0rWLS)=$ZE89@$sTp8(~88Qi~87!Kp6HjoNxIIdG0H{_CRZ zwGL}hAT~5*y+Hr2P}1IE>XswMpOupdrjRh(S}wGS0aoDR%SDU97F-F9q4rEaV`U6$ zzyv2_KW)Mg+?uIzvtEbP=Ky9vnZFlSkdH?M3K?I-wHS~Jb=BWoaaf|nWgacTTskbX zYzBjyC-|8_r+q!puDw-FK)eSaDr(Eq0rmk_0zB{A+dc;ZaQ$6?RR`_$ma!EeP z(0&@UsG?Y-aMZS|2uAA%+^S#mZTtAKt(|SV@eL%U{isMmL+xMDlprD!To8|_O#R|| z|0;cs?-|!VrmM6UBKThm@Y7_Bjdv^1=bE7#R_3Xx+bw!sC~kaXWkBN`Nd=1j>pvrp zT)=VNTIw~Uh0#PsV=&e_q-h{Ht=y9!W*R|lzLKd!N&wObB#Y6pNb7@gaW$XHt z?JjF|N5e6w4DwHY+Y3^c)cCSVo(;oC75@QxYoAl+c2&7vy?m~AegHU^qW#1-;rR!f z<12fPoa=r2$Q?|@!`NpsU3SaH)D4@^k^ww1+d>8E@0?~;o^B8r>L#cjiBG8o$R}lK1j__b6i9l=7_cTH}gtq6IspbfrjoC(yF(?E;Xs`|;vHOV*_0{=K zNkJ(3pI8HJgdgmy@N;c^?qd+s9DcK-(Y@{ewa&jz4|m=0-$m#D z`DUa3|Mt%F$N1j|`MAKqcT^+oLyQik@fEd>5?*~+8*E6WHn&TBsa=P#on~AY<+i)vTx+es;rh)w{)R3$lYq1blRmWIsYb^BPHKOP5wQiKNARfLp3Yz2MQHS0#C;towcKkLMhy@M_b6mX4fZc9hwnYu=x!E*~ z3fGyt%nmv~JI*bI&9@XQn!Az+Ss|UQnG^ePVHT7 z4}47iB{rmmLws#LQ($x5|2 zVv_7>%Yic)SpU2PXX+k>1gtdI=+m4+0uG&$2rAvy6LrJHA{~sK+3KWf`Z_Zsw)MdE zdk)|w^rLy~tQZa#l5?7j)x;W0;_}oOH#1P`>vFvbSvRrakVa%rjj|P^_l1j2TB9+E zb+kMbUak-2C9bhK&%s)Hah|f|lJNafj>UzJ1Y5VQb;Ya+F7!nK_7+Y?R7gHUKb^b< zoCJ{)DhV4m0iEb1V91uZZX4;Ks#bqsOK zCV_{ec16+DupOg)ba4(e)IJ?+#`&=v5S|mI?PzjxeidV4>OMK1rmHvUU}CU~kWBkr zD70K^`^KVYAXd{HooX(*uMJIz4gN_IL%wEB04ujBp(~A{_C3?Qk1TwT2*KP^M<6Z* zdHqS-fzX-_Xwwwai!HRn#<@aR2$s;G8nZJ#+eEC!YNp_3LNJ=D9t*6to2H}|B$2gtD_f|{PQ&;!!M2zJ z_;l!w&W5WjKt+`$N}s{2G4TeqE}Yu)H>rY@0OuZhf8s`TQAsdIm;K!+X9l6XN@S~! z%K#^rR~Ra;=-?BjpcrRVBg_i48}C34X3R4htZI|{t~(aebi;MT;Um_97an11%J5nA z>>L9ub+p%hTE$qJ$TY_~!C%N$Mq{}}3pPbR(t=r1u_f(#BFCH%G$^x-NCf$cgwD({ z(Ag-3t)ii`T(zXk=(yVE+a~R$*Jht=Fom`l&6catYqsNpLYudx*KF4|tMwI)2mDB+#QTlx z-?cb$JR~+`*C|?6=V-bWp(q?A@^>aOZKIxVo2?+kRfg}-Buk5y&8l~c8&p>_(<(4= z9@uZ^ZjNHrLMRi8aJ!!|4>Uz-iv_~(?UDu zhCQC>i(#38XF2)J>ltbEV#*?aV>iChxf5}wGYYy^zL!vd!pkZtA8@1Cb=jD1ZA5j~ z^DZFPQe$C(y~q9DLTYszzrWm7$6(ccGF`=`9G|gEl83p!_h8^TwA%8UlNY`qQy{Xo z&zy`-tsuSk(mFN;D7VhZ?-wbABOmYDv>LA-4K@+^>Oj;OKd3S>XO?aWYeu%8>=I3= zPPjmG^yIg=3i-ylujctumh%8v_f(i>fp42%E2?hgdH(l+U>h%jvLG#WRJ8kG`&HEX zn~04AVorLU>+%m)qA{N8$5uZv*{ntD)o(62)BFxru_?iWdm%0*n_#JvoFbYJ3FpRJ zd&Wv$>2fX?02CGWzBvd2r9_DC*b2=m-vwC%VCoCmCI5MfH{?M{)hLcOs{%z@{D?F>RrP}y< zM-P6mPn(sa{bE3<5(jT0fta3F{80Z0#10R^K=5E3ttsZO?-!C!W3xu@h#a#NMRx6? zo`unrP;PTWw!K(~hq4QL`}ge?9TsvwSg8&X7X2INH@&|7_uB4Xi~PTKwq9)2{lB(e zJotGEtq_`z^gGuS%IpsC=a1I+a8GMFJ;jwb4E$wwQCw`auGdaT`Rfk9Lu z0Tm!!__iH99+p{lLWWMu*EK-jC@EJ*6>D(r((`kCf-XRF9SWU~JgBZYhCq|b1p>y< z#Vrlngg&mrIw~_sCs>lI1O*foV(7vNz$W}kq3+Nd8V8GfMVm}=ozae@Rn&VmMujNI zLu*zb%30nA3{6;b)lT9OTASdRE>MKbJd`A6-Nyt$5gcV1c|NkedZd__1gyRX+Ojj0 zgsZDtpf$?9ICJLWex{U_LML7Ct+#KbP3x*Qs4C98f;{zPBeD{kHC|DPQkvE>Z*wwX zlAsxp+ETY(rD`9LA>+i0eTz0CNG4f_kur(aULBo+y{o6LO~~Ai)(XaDPg}H{yI&Pb z9+H$dJHO%*-1RyzT-)!!)8|47QWsT?)&(ly{A6SG7mj&GEsJiqRZGob?`6xx!WxRM zZKz4BZ+x|C!)R7(3Bwr?328fottZXbRC|pR;hd%|Ne4%vrPQ4MnN13oTNl4J4Z51> zD$tDU;RSHlL2Xt`qa?1(6l<-w>!Ix)TB{sf!esT~XuV#eQQXp~Zhs3`zdA~lZd=W- z)%nelM`U)rWnEee);DRk>gQD<{dbhI{=A>-$$vS$`~2@aFLs_c^1r{>+;*_^LzMA)1*oMFV19i_AkF%M%baGu0PE?q1+QNQ^Ofs#?eRmH>wO-Ki!W zIc2mea^jZeeXfOvwg1!87KU6>T{s??U|GO=m;xMbA%fRwn4(TUWL(gc+~e}hxVOPz z5kj2pt?LSSR|p>9EUAjH4{1Ik9Bu$Bk@-da1E8z=yEn&b+H0{%7W@TC_TPf#O3NPO z?Pt$LIq8K%8tOo&M3zMr8=^oO6DPc7*z|rDvYAR??|^!52fh*LjN@ErD~@LZ(Qs>c ztg6M>KzdP(|8kXzq7r`3ah9EHQniVjd;wH15|!ZIkN{*S#A$;5nFO_NsYGLJ)AgDS z6=PhuC<~G!PDf)~Ey!k=wol-FXACrohF+j`bfxR0&X8aef(DF9AvrEw(W!9z)U1Pr zp8D(T-RdYhhk}@^74g{3KUHW4fdE8$b@6ngK1|M3#`{uL=CTF(-sd*mDG~|JbHWX| z=~V$Q_seoX5}CQ`bV{fdc#x6Qe~s~wIyI0waWg~p7vgB`;hUkV~tGd zEG;9y#RHO64iL?5kjJaL%i`owa#p~T8suErLje#SAN@pVQ7KGZ7`cp5ZKHb_d(WaS zQs$D()?Em6OMeu)w1=J|HdD?enO&p4;@o)#&U27SL!5LZS&$f(LcX34-@4 zMfnPwDuZeafB{o$9=6QZIDqQ+yesYGp?0pta7qwO;xpCrfiX|y7cupA1|h6pSV zG&Hrj#$F6uWg2aTYQvXm%lBhBAoXCi`XEj~h*;BM$0L@p_W)mc1m(V-rEizEXqcttTaR9+Mo%` zsbp2Iqktf^sI3~Gs>biCw(T$Te)v_4qVDeITdI4LrmSbysZo!Cv>ppizc@ylkl ztBw&`)BEWFxNj^VFt;|7M8cwLq4r`PA|@}{1=0@S=z`?asulV_FVXHr>@R00`7caR9M{eSjgL=T`{NG>%~@`I zWAd)+B9sZ%1*SpgHR7TZ8mf%NqT5p7HR`bJERl8?G7al?38lVz@6%I&u81df<(USlpm{m z#K7*GVxAtkZe2=TM?q=l3z#TL8012IvZ0o!gZlJ|cv_WzuCVlrRfe_9=Bgpr7!^|F zqo;N;o>rx+uXHgjnvz`NY~5C`=0u6=2;_JdPV}^&BL~9VgmEqD?u?b%BeB8;681z)SIPh_L0bI;hAL0ZPUo+&YsJpB#~^1Kkk( z-82@UlY{zap{O5&o720E+97$@P&1dj*m2g@}Vd^hVCXkVv<|t)Jsf1_a&kD~8=C#3;Z~&7Qta0be?}%?Kp3={d zR)*!HY=$^d^H5u;b$y+4Mz3=K$oeen!=kip>`KP!z|A>az}vApAECL%a6YBIAJM?!Fc{O zK#>opC3SE zrwA9e-YbJRAlG;qNqn_d!OMycd+6!XNHwMPt1-<8x>$tZMSY)iMHzUdHP1f!IUIvr zvu;;;z~s2{vK-8uNe#T%9Z}a=G;)_y;B?A=`CE` z*V8JQS~pLa-+KwQavn?Ai9glijdcu#enNM#Bv*`IT6vEOyQH_^B=M(iUZN#2<89E0 zhq3nSb{(?$>}V8!O!H=r3(o`5`@UU8>w;|3N-%yc@OqL}z%)A8_a7y(`{7{U=5G&; zz>TL0OKVj}(Ix>ke>e8e`iPzpw*Hf`1gNVzLQ#U_M5)4l%DtAsTCdz%!ABc)JZ~<> z%Is%teAu})a}Rb;NSF0lVmi4AGx9@2!w$9Zms`(G59v*8ZA4`I(9pCuZ@zP%Bs$1o zt}J?}VZcJ7CnoH`hf}?GwvN&?1cqraee&^>VMZqUY@-6#Pq5hd=9|h;;5N&z(a_N^ zC}wrX`&AV$@5)SBA5heM2W((+`e_}l5?c(qfrrON+Mh{P*SK~rmfz#58bFnU*6ur& z#{c?Biq@X|)`O_M4mzk|p{8ZN%-ckMCv8-|PAAt-a6chj>cUGz7+p}^lj@o^ z6$D*kVyz}AoN11pDt7eLTojfX8K2;c{!UUGtLPl@H@DON6QNlcEXNvTW;oFg6#H3* zqF?^!mpz>2(BUZB2^1_H0qL7Ar+iP4(&X)qzSD2`*) zAEN)K+VoAE8J=YS-$id_D@JEy&aNOX4r;{dI!GQoFuU4;R<_$ZC{(UE1HyJ=AYIxZ z=#JLFSK-RoXG{t%oSOoZjQ4dXX{KaBNe1TK9+-Dh{gh*3yjt&hs5KIX1;*_g>oc!)uk7K#C>q z#nmE;1*>S8tU|LI;)qFa6rI%8usj@}s|yNMu5n;s=ti>}^a4@9zMLK^wT?`5DO8W1 zOhzh4Ylh4f0SpMq9j(WZI#5#!XsF?_paRiR&b&M^;K&3Ta*W=&%)63Vh;>91F;{(p ztOL$E&~Mgs?_8MPyyaZR6#bPKtvTmg)4)DD*hijV)JzEC4eDQw=GOjhhB(O}S6uy? z-1x?nIUt!~7N*aI6Adc+iL~Be=wf0aUxa}v`t1asQ7+!?AMJnt`sDoVAIGoH-|Zj$ zwEy-3DG)0*`5Z*yQq7!ec{hAq^b>vMX5ritoAOEE#vQ!iTZAJNwICKX*RMN=n6)>o zxO_qy5p(@o6Sc|pXVzIw`YlUv=3)Z0xn>0g-tGEH{S}y`CWZxFH$O%bNQ8?*Y(Tz@ z>f8D|fO-Ely=ytU8ZeugG3Gt|M%wd133M8e%i(R#q)>vPdzgd+Xbf}uQAjVDi4CX1 za2x$dqy;0Ly)PFG3~QwzRfxUqt^<}5{qBnMnREJRb^EaUi6XP1kqg~y<{Q$FZXq2^ z7_3G{C(%-xABrG~!qG=YCt!5cmDNFi(s?!^IuRXMf0r|c1k0v6Z|AzTdAja<$Vcd< z`rh|;=}Mbq<^n4kXNqz`@`M-%sF&dUT}E5T&d`fAdEOEqQGf!_^z_NTi|ecD;FOf83-Ww~4qk;t<(dHJnDxETWo$Z37U zG}iE0BA2yy`_5CigEXn`R;#~YL|soCU|HD5)pzSBv+81tL|6y}$d#7Iib$4fX_c8y&Lwx-FUv_&B_O;foZ|+*| zFa75`T%alZY!wfkMX6Gix(kH04-@%?tDJgSbD2^nxDP7Rp3+N%p+$`eBm_6e=@enQ zp+~ivX#1Z(qtF}7Xev~aiP$q2X&+sZ*&eD$Juxw3>Qi7j-a|4I-ccyXMCYb3>FNPR z((PY5f7#!$GKbQc@P`h5Y;ErC1Gce}gkO98-|0-&cd!W)1?dUL7(*EWw)Ym>9|MH(}@&8N*uikO~$L$x-cboYiAM5`-$j4_yW`C6yX#aw6MiYm< z$_D>Dn-v89&=0vo#*bO5xYW;_N&+SuKRD%=f~CJA18hx8nA-i!B)K=?@I%HO_zeqw z1?ivwgG`K$S!!WnPS6#nQj#3e;m~3Np~<`?wv;Vc5ravX^5pPPq(;@|WH7i@ugZ25 z@Ox9&itgkR#+dkJ9T!Z0Cl`?2j}l??4OVFfXWA1WO-)r_GndX}L}m{VK-3VKgYs2Y$ zc@R}NuEA`-D7xZtyP*`A%RU=Mz9FQ8&ASar{A`B}2a*4Yzu8#(_%Z#w{YSs|pKHz? zwV!Bz)Gtm!`=YI=Un@0b7C`1PBQA5Ey)YHZ`b^x{OTpSS;rP#D-=a0G1b*8tC5VjP-b5jdoa_iVhJ*W;lp-l#1#lN!M-HjDkP|55HB`-~nTqt^BW( z7b92x-@}3pEpQ`AD0oVaC|GW4mW4U1b##KQ#f|9D+EVD^dl3*2Au-&SAKZuH}}H$kXKZ>ey>(zQpgg$Lb@ zxAZwbz?r&TGlM0Be_%c;bt&aJ-Pfy=DZE2r)9*BoX06Jmu964NIAp3WZj1`d1qq$t z%=vQNsK}p6L*r?T4kfTAy#NdiAaOhS|JnN+=tz>QP89F4jctlu*4P;M+XDpEGp8k? zDoHJM&$v82wpy*3k=-o`Nz?W)o+E`aqf}{SW!7Y5mAX7Ve~&Tyys+5p8hC3K%wi1t zX4$uI0UKC`kL3Y}2du#c7IyiV^*poBV6ef!!+4DszY{mUGb6LA^wk<$d5*`etc-{o z5jSq!xN-0ACW(wq)T!w7S_OlO0^}4v$r}GtWTW%Bs~j4xla?2Sq9S&(<5*O5-C{H)g*MvtN%WQjXSD-M>@g&Ix-)(*LAVIidzQ0RMS<`g~6RyD)v4 z|KnI5)BdB)Ke_Y7!}fvW5lDx?Jp)B4rwIpPiXNK3c2y`jDc&WN8+E)mqJb}UH^5Ie z8knpA=$rISoJ5_lOO@>hj43*<93Ua?D7^P| zZzyWxz8uvpUe^|AH$tN}xk_Ps^9Z!450@Bn!V?ntL?r!yS#rH z4Z~QrAVW@ua##v#vbTWUV-ARnqafO8c0;Ro)=&Y4kt~q!myuG2ky>(>C3&N!a4$3Z zmGOha@;Q_FJ!}0uZ~mUKtb(3aGqGQHMAnb`IGPo|IErdyVW`2>&}tTXr_pp+)GF7_ zGG_@nC?nd8ID{8cb*C}lK*`cI!&|tPy~9+DFzW8n(Kh`r*d1h@5E=gk!GB=Q*p7QT z*Mbs#HrI101a9OwQZQK@0>3G|lc-FEP(hi}Y!PN-&N;U2$P_U9*^|uj``MUqY5UII z$r>oNMOiyYjBwwOdY-MS7zeYALDe>$X9g{4TEn?<=cIe)r_ zk8=%kh4TPQm_)tnIB~DtJCx(;vbZr4ig5j#J#-UAtl}t@&RsPF;1dvN&B}Y3XkT#+Q##|DnUlt-EH|WopjoZMNznKi zJO!QH!94{{)%#%Xf)0T^z-KV0$2%McO;LUTC&J7Lqu}Pz5*wxNgc+IS_9>iqe{?*K zg%-XA_!vn4KH>3DQ`h+J5bvzh+;9~R^x(6qiT5A^w#3QN`kb^mR1ocUI&qS|T0wPq zal1OeDa|pr2lGsu&sVrF_q35kM46+SEsT`-9Bm_VOP=C=sn`!$v@1@VW`5IzcqHfv z|Asr*p%Ax8N)ond1t~z?#1aLB{oUlb>oG-L+Qs3xF2Q=M5)1{YC3^^_0nayN?{_6K zK<#OACF>0_=YwD`{gP#UzGPX?YClqQPj@Z+0@luuJOb~@&T%n5B&z|?gGKA(M%qRG z`n9BQBB}9Q+69FK5%LlCDu7kD2|D2_U*z=U6K<#odgK~OcF0PPBy5}0AQag( zV^&)Nd(9(k*GQY4BG}52TN6!jlBy&lQ;O@X)NvrTRntc2T9`_N#3_-@EbD01jX+Rp zRmm8hL4f^AQskI~aYtMI8^n_SX#k@bGDIW-+a>)ef$%RYVd6pkvE7HmW;cY9$}|^5 zN@+mcngvUKyT-Vd@^R%*e?gR8Bi+asj)i6d5Kfe8J&Zl6ONk&{IU4MEn|W0Sn@?TI zyot#{U&v9K6gIug=ln~4o>!(Wu=hMNUPo7CX5K)UR>e4RkPiSk0hr)P7ze4wQjUS* zn}u~jCV+WjPsaL2>b#Od6@&;*!oZG`%g9cLs3~*dQWH?9L0xlvabWc+Cq*qSiWe6t z+t}!@;(^aGq9ID;?Ojgoe1oll5w|Hk0GMIM9}Ej``_@n6^ZjHroyKA;mD} z(|Un9gEu2{^etmEM%rN{gV#|;Ow7nby^QE}!e8kFi#88UO`vs|u*1m6)1@TSOQzyN zA51eA{8BTm5?0M@l*K6Wk!3?@Rhy~MRvwhoV%2C#n(1>O=3%G+*?)OMq&ZL{)H_~Zwp-6-CR*w_i^$a&(g^h|W@{zkYj_ppCh`|1IHO77shl``nmaC&%cAQ*WdO(P&5{7VHlZPX5!h*0hzO=-m-YRDL zl8BhX9FW#BsUHHT=cTTzK-Iz;0K#{`btrb4X4va2zDl7odQ?es8HMAO23OVR_Nl;G($X5-`qA?@?*|>Z?XTF|O zucy)2avarkdU?^2adGl#N?hQ8$`lK5rR1X2J!m2h9Q@*}Au|+hIeMZ@UACS1%&3y- zKe&g35G=-HL7mjO4=cZfhAEKid>kgOMo9#}H6iYI8+*Hq5@W1*kUF%@e%-@~k95L6 z3)9zj-78MyFAbJX`zncghJB9xWu%8|l0?%s$&WjPsqUp&>g@?}gk7^%tgPoP%n?SY zkyJg10cBk6%AH`HBt4SUaVL=08|TfYpj%TQXDpi_*rrouT-uJ~Fxv~Ytxrv$RS1&? zpG)5d&XB7aQ$$I-C(*^XyFr-Ng2*_WD^!Arc!W}%^f?}CyTcB5JXMoeWhm;lw@E@x zSlK&vjn-f^p|v~e3%G+Jw_reM-5{xMpxa3LMMieku*r8kPl_H7``oG6d=deh2O>YU zIuob_y9NlZK$|((>=x;1StgpbtpwcV%p9=#wIGTUG&AF_HCx}@5LSm08VWH93J(64 zrBs?=;ilCYC z!CShc*nnM~_Gv0I4GJiD{zBU=^V>H6q|S3OxF~fjAW?0#u#nu`JM8cNRBvXRq#BkYQIUmW644;?2$QXe<h%T6&-(UB zUjU*}eoredSb~Tr2NMA&-IP07s&gh(#_v)p2zlKkVM|_JCi641aW)3_f}a~`o;#?- zO;!spQ*vP_DChTt1LH_KJb07>0|_aOR`3>fr!nt4zD6DTz{!xV;eK zpzXvVtD3j6GF5TUlh-O^R_z*b%nU{uM^!*GuNv=-zGg>4``V~i>|ZLwVBNUtb_BIJ zjyy1%9Ab)AjcS!Yf~?|JuYfP?XC(Qb5Vl7L(axdTe`n?{%;xOBbJM5t|2Q5~{x@+D zqC47zQoIAwc@;9WVH5=(3HwHd*d|VKC;<4x_h4rtH-fbI=8s?4@*kw;_=e~W(S7q9 z^HEXArT-z zLIgJ}8bmuKVKh9=W~t*R-EsPS%DRoijR0&^zhuAEVpzR`>T~fhHWa1&xN4Lu9?GJH#ly-E68jlePEu}6`D^PNJ(~RQ zVTKaEtjZFf|JR};$$yRIy%|Ko(6@l)^8fto`I+qf-|XrA-!VO=V6ajGqPm$25JK9S zq%fWP%yfvoOgh9m_>suGjQo19g(*t+Vo1V_)NAnzyQN6|!akg|n(1`I zkji{(aI+ENurG*db5s?9q73E0onmDjKGj!?9qjG08Y)QKg@Ml(Ym;}1*FP?(5wtm| zX~Qp6z^!y6T{EMEJ7o5{VMG#j=OMC6`(2M9jIJ9$_R$)sSFF{`aoXa;gc9;-H%I{J znNaR(j8j>3Lj9%lFAZs@Ze%#S0UE{P9mLUsbm!<&MLzk};yvBk-elou16DN4JktXcpM zQQF(=8bd1M0Xs{JNEQwYB;sXwA}%YISS&UPTB9PCdjZ*#p*1GDiprE#qb=Mab%2mi z-b-4_*Q~GlxE<;ZJr5ynCloEW`et&x<~DiQo>eYsk?;{mY?XK|;_c@1VvofM8UwFh zBe93}niVOSb-s)7vabuXWQ?09^8pUoJPj=IP0oO0H21zXS{`@#y&AbHsNg{;p)sOG zs#KApxyq$cqBAzzb%@0z*3ytwWu{=GMJQ34U?+(?cn6@dx*a3it!~rN0I$)}0xPML z%4X+Z&9lWjD($$w^fvPI1{Be~fVJZzwj*)A&3~tJg4ob4KA=EQ<+K9xrLT>3NX2j* zXPaJ(LAq2p)g{pYg%!BwSr?p|Kswp3m=raNX0S2aO2z98_*C3PvY^U`r`!d^cI7MV z8J?gaPFSrqkL^@)1l1VYQ<^2JW`qmXj97Z3|5@%b$H}%-sr4nsLM1j7d;X*)p<&zW zU`qGm#HR@B?$vGY0VaEPiijF_{3h9dyzr(an~m0)pqb~~Ey!ygG*KZ>CLZomg3ieb&hdWu+Oy^yESYmm$caNcwa69?&4U8X(~(du zI`=SFbhvl`i~q`rZ4O4|!l5(}`NAxnLkn1kT2i20$S0$7d zfD|LmcG-wjP146v!M-Np%SmcR1%SGNX3A~db?uHb0Lx{R#5p-e# z9fEEIF?ZBL?$|}#00Ech`ceTmP?Y8V98RuXo8MS?pg^u&lXAf=*BoMFbg7mf2A5QG zNU_7vx`z}{{`RSCdbY|YfBRG{jUtvTUf-ug%AUaYvEJml`*gJpSVqUSh~$J=D{1I; zbhNAJnAgzY6(k3%Wc`$^m4lds{B6rBR94TboKe@dY;=Nen77{4V=s&0w3{oJor=ws z%SAekzkSeSnk7I-JfRI7-{J(`HNyy=m5I_CTWA~;0hmJ21t~isQYGCa(H zK0!2Y6V&Rqaa2nP_FS}s^+p}roxM2>CL3*7pD0+;@sgbkoD%9QR&PkSPLTtNZGg2B7O_H z?G|?s$sDqE)mNLa8S_-zSD02Y6?VcXH%;mWOwiLn2F9Ixq%49 zX5@**`OO1N5n7XaP~(!=BiOf{p2r7qy@ffzv-COl^y`fEz!=VsD{RcDTcBi6o5X#d z(zA7HT7}(=){U;OUSCjOx;E{Cx(3u>y1)U*?>b3S8A!no`P>X70_Y4g^b+5CG>n50 zk4Dot!8@!FrG(a{9ngpsmskr{n^m)1b+`(%I4}1F2~E)+;l7K?7-+7VjAE>yC(Vp8 z0Ywx?M4c{4M1^G$^6AA95vjZQab1K|1CWrn3!ZGG-AVgbf@G={Q^1s-TD`u2xF@Ud zD>eN14Dv3E8WyzwsSKXfV{NZYi-{vfoaTzsij7#r((kIWH;#lQ<E(VZU6RXRIb)yAv&EF;@ z(!gJF!h{7}56F|ANIE*e18ylo+i}_gBOW-sX;(K4fz+6~#>{fb96@XjXCrfTS@v{N zkR^{6D#ey%skO8V%Z_Cpf(DZ^f3UW!n{}D!z}VpG9$NxDgNQ4r-S#*t+HS0^&9K9{ z`#W4U(jna06R5%-w>C+3$WmmOw?`EOdFf`;XO3GD^ax+#&LyMy$F)GpjodkAKhQi5 zb?%;5AO=3Vld6L~*l+11=g3_`Is%R_NC)v{0lnkn2j#I7#Su=HXX+FVL$ETYvC?R= zcSAP$Jcu_pFN4{OPl#-!Kz!zBtB#fc&9W8jw173exZP&_=}X%^mwUp)xQQz)Y@5PgZs!Sy-77aG6j>f5j)TrfK^tb_FUK%2^ z#IOHL)ZpB}Hux~4EgXTqTdn}0u{(R?)q&*NIty1?9_;uyB?X5;9vH$nBaY1GinrDg zHRLkx)i@#^ama~)qO_YtOp9nX(O3X{$k`Z2nv=QxX1tCTdnD;2pM=EB{VRj;vO*~K zxwPWG75%u&_&JOz&k_dkP5>98;z8Co)>fA9zxt512JjAMoL{dxLG+wMZYcZK&EcSv z_$9|NL2&a(Cxo2wn3suSpRALRcxhamrY$pn^GMasXTerUw)@#T6DCjQQ+=Zd0S8fx zSmTJw*4gQhr>kLyI63~^C=7N9he+IulUbk-yD1k&wtQF=rhh3Ka6+ak6}i0 ze1vI}LPCwz*qwBIxMqxLHm1*kBRAp}X6eGi-VyV?UuO)L8;+<8k_6GbQkrLh>cJq| zvUJ$(-}&fJBph(e@|bNoW>~$xAgy{MYZx{QkD$PaMu*Z-otvw%Je;JdwW3tDs)GPS zk+a+s93N^0F0088-1j$`9@gA(5#XF1Hw6VtA$v(DVKovWQpx-4)_Jmu#@bz)&I|j5 zh3HXKW*|8?Q8x-69n5Rxf`=`ayv)hYRL^eA4Ms$$ zTh1ECRkXC(_;4)HlMPo3=y9W@m<|@whCgUPPvIC(^s}G)zmdRShRFXgckyBt|7C7w z=JfvWI3CCSUk3f982d$`yNm?Y+Nc>I%2PHq#@|KVlvL+KS`{AE^n5ye73j*cv08rfcCkj<~IQWx&V4n<+ zeB#1AspzOC@~HV`z0IAD#tVLcao#_YKo&<}pH=wVOR5s34$9w2l9sq>XC1U%uGt5O zF|)m~GbB0by>fW~#V)V%0+({bpL`#r``had;x&EQbOKHW;Zo=zlgnyYIyjH8YOY+? z6%9Je79=^9G6#AGPH34f=kFm$4}qxr+pBi`!{?(KJDUDSQt92d*@jcdP+H&s{cn19 z?n2i8>*DlXr~2Pz`X$Ha+1Ca47hn)8{YF zWzTZE*^`iv^l+3KDMjSfmsL@H5Gmro(~v$sQ4lf>9<#%U zNW?B$hROl|&veprUO<;;I>=g3hst?ilkLiEAPBK8!nq%-*}&1{M-bH2ckiY$;aYXw z^1G~7-Dwf%5oAR$$7)&R>b--ylOc#A*}TB!*LEsilN`H_fJ$E}HHlWea+Ek@?y5wO zY{UXu6BXAyK47|~JSLub$Cov&XZtQLE);Q9gV1rSR++6(_k+jYIT$M&LGEO}OAcy= zMD}xMq{#HOio>v)8v!#AC?amks@0<5EN;wK!{@5e(U0Q^ju~bD$G#shR>Wb=!!;g@ z3YL)pZ4Ao)Fg=sa|1)>j`P2MA$MWQHYy&W2)vdTWnFCERz`{JN6x<0!&dLVr%~W=S z$ZsGHDN&K~uTep;?KO~#f5eXvAl+aqHtI-U*+ynM^!3NEvl|2 ztK;YndG|){gn4pGSXWh|wx0(}ApIh;aCjZ+3WsAMWwAv&NLz2`Yl6K;-bQ>6S z{+pYf%gFzWbJM5yf5-BSBL5?j?#0Qj$ZxsK|1xu1n%jZ+IEZ$%RxdUPvt-}7Ph|M4 z7R9w7+DQndN3&lDVtMXQ5az`cxV8_(^9;+ZH*!(2UaJ7=2HPxPS2)Oib1+J2hj^^L zPV7ssMczCF-(NKb4I$j=IHsb4kf@!1S3{6#w4q{9YV1gz#$FsY(8j{50XxP%Y@oa6 z=4OEc)`5+Fhp38{#0=X^rzlw91k}lmPE5(QI117jj@XYsUa8e;N5_0^)zqzGK25<% zXTCB@CG#2lV{uPSaL6mBUokD%Cd*0(;@c9I`@+?T4!r+&VxN}{(td#!Fkt_mo4$~} z|GDeJ>}meLV|hl||A$F$ZAxJ~m9~(-*>Wx!teDcZj7OBNo!FP`spM91{kK-W9+XzK zy(d902+0od8{GQGhzi4aZ&m)VNIlF`0IEP$zxC-axKpT-jpz6s`8C`*C*R0O3iX1Y ze$}6Tycg}^#GhYXV((fpO~rPrTVXGkRu}9St4mk(i=-RP(+4RLB0lMcq=C*|>(X?M z{lZ&=ld_WeHPjBG2AZ3mo>mG+8{bfGD7hL$-5XYgP}zLcXZ6u;rxOy0w+io1;%d2ph^#-SPk(nA731N8H+NWIyzQBlc=H4EZe@ZB$HW2Y4r468IRlaS$zK z3W{2dQ1L5Q3(>>pc1U_|5}ji$v;T)C&pncvKB@X0U>5T_$MMXo*1XCoxb+jh ze@c%FXU|@Q7~14WA}QoBQ8(mB-g% zcv}rk8AOECX=|z#$Gg=As&*1m6Hz0R?B9aws{OT8#%jV6-$2z}LORtl7cLLiJEU!T zU}d-{?{}8#2m8)l%V6dkqWWFZ-$(6?Wiyq30pFQ^K0OEB{}1l}dwzQEV%Gob!p!vP z{(mgb2=*V5Zb@uZI%(3aGXVKU+NYt7KSk~#$9Hrbm27#fn~+Wzc$gXkn3LM_8{XY^ z06;wbb>hX5PaB9|hVIvcMv4Ma(wO$)4y63M&}yu7M%<&?iT$ewV1>IiDY+>`1pz%g z2qsN%vl)1G8u-M+Nj;!x5HkiLH-NsSXglsk{%V}0w2G>C&&|zNU0FxTqeuse#2pgR zR?swf)SyF$mRO-cst{{kYPL1%c~w+R2-8Zul=!vY`F#6U?(>4-o!<}NS|mCLTrx6y z&Z2pp){%NG;&($LQe?&vYGVitjACEhrK-UzVEi-=Ng{?vba8!v&1@|iNL7>*x|d{eHKuD+9Q1FR)-Bh_=JonUOw5$S$nzRk5x zElc8Zi4hUW09BG$KD=-ZVcZ(U}Y<@GJ+Vzx~J;m@4 z><1B{bTx^$NyGRBp;nr9?kB1J5`m0i)jqJXvAUl5t%K8615E)eclIaKYuV^3$HKZo zLacY!3)Uwck_6!F=K8UTgRq;BjaEWvD-Qhzn#s6IQ@aB-JyWZ0l9XYWY_p@T@tYU7 z+c@&G6_yWh#><62WuinUHr8uo=Da<#h5U{r&o9T(S{$bhK&G~TCfHwz!an=?z91yr z9WnPIiF#(W@&asa<@KA_7O!1hy0)}oRSOVP_a$*V%P_J(_XQ;Mg&p1fMFWLFJ4k80 zP1}!M9!{phU|Uh)Ai-Td9?&~(9HUnEJiMQdkR+x1X^fTI zM|+fpC9RRvo63G6OLlgH0VO-T!IXzY$IeEsn;DVnEs}ttTg4*1_ipsdLwulb;3x4fNRKxia=jEdA78oTZ-@uED{a>kKI$I0VD4Kzs4sE!|{F{i1HU zL)3}&gc{A#1vTAz=kvRt>wo9kZGLkORls-z*=947JHC7dB9f-a8*9=GoF)%=OPev z(*}C@5sO{a4;sd1Fqxwfz-LQ|c{sq69uCbJ)6-GDDnOtIK3Qxw!5<2i)Jk+E>92Jo z&J&WFHPQ>no>&X4Yzsf(pow|oWU(zPJ715RTj|2u;{3*9^18v(=S9*&h+V5_Y8aKq`-*>v(Vc=Qs;l{))Anah$V7RmsNoCXv z0}`cttCDnim@8+nsO7Z>s&2FhI_Kd!J3X9}iJiIThps)izJaz0+@Ykg2@fySHMB5q zLaL)6LUH1gMCHK2S>K|N1F1u<9K0QpYTnIb`{EplyqrZ=kMFRTWrG#{jx;O4mPRVJ z#eTRYFSaR5uJ7JW3A{cP>jxL>HMFp@yu7%uF|xR1FQ&*1;^p5m4Y(O6dpPk=*V19G zCC>L>5J*|0`2WbCI8zMc`NN+9{=d@~FW!~S|8nu-ssGQhJo}6PD)3Qlk+5B}x#WmF zR2?lI4ZPn_4Q0GR^)fNtEz?ej#_Di^RllF4sH!rLIM!D^?S$2F%Lp}hs3K^j_0PmL z(@Tc|eKVdx{{QE5{(p1l&!6JI9m{hP@!t$SJ7(NBSIZ|0a%(sWN5*+m)eeMa)9j$i z95p1H?(=a&vAJ44sr+!n&}-I5GX))*Hf+28&@1n8Ub48ni7n8W|RFgtgu z{~yb9*!XWpgJorK-XUUGS+$->?5Y72-U`erQ*s|OR#lb@jt`^i1aZp#C_D;GDtkIc zLNu_MXz)B{dFtTEk|qU*i72V+J;6wlB{aGaB!%NlF@U7`0r3}bho{dC3@k}7k7ofU z;iV|`Kup2UPAjB1ZLKDx8Qf?f=~|a_sT&btQj~H7Oj>x5M~fG!f4}8g?f&$?Awa*3 zXMp}UGkqb8|1f)T<`n(EBKK^*+ zEUGr~E~z3v_PR_xLX>ncI2@rgMmX@%{nuZM$c;3?Je_EZbd!Llfv4PPWzOz>oFN@s zQJ0dMR%RLF9w{JUzPVd}S{#xrVNA%F5^5@BuWrViS28vQ{h7xj`@A@!X@UdpN0Bos z)Ql5G#V{irkqJRdE;bTJ$^`mso@?~hv%*Nk?bBvp84DcCPa6sf%>?_=B2Sf-eLef! z{|AHq8PCA`|9t-c^V4&u`~Pt~w*dc7-y0X8=ea*H5&v`uMj=$+0a`&ax28QXO&o+( zR9z#Fb_q?1FX08Dqd^=^qU~-9RN*j0aWmr#IjIF&(Q76taZ1oG=_8yFoj|>g)=3Hu zl;^Br%{pkNvCzeWChEss33IrIK@;PX#=R|hHGaLCIp+=S@wH!%EiFV&3YOpy6dg8( zU|ug77R>Qb(Fb+&#i)ZN>!_r@LYTqARab^Dc&mlv=kc?z{eOhB|CxdN|IA%8(=(a< z|NLDur|17;dG?S02f2@bDWVEaRb5noa1sd zKz#*MP%sVdp>$&R4IIdQL-rjz_?|xO9xC#lbA(0%+{;0dX>slc5PP$MgDBk?5=SqG zZ>Ots!{=Qb7Qszdv`>_~q6$Wbx6?K46W4C23Wgny(UI)jWru^XbAiZZS9l&gE*l%D zDG>h(;^-PlTd|L-%PX4;D_5^BE^I8VELT;-HK&sZlK653sC2p^2Q*zVFr6+|f=E{| zA1=3NStN(xmcwr|d~F3=L$56t=R()d12G^9KZ zu-bU6>fr^FfZs*6Q3YhGa%?Al#HdbIML^+bg~b^|6@M-14_{iGD5{S?ey*tFODoHp z*A_P(Sh@nn%ChmqQs>-s} z!4%}Spv<%@IJvdeh0XQFwd;#(&b9|)xyg#wmzOplSXtj#p1-!3uSsZ0T8W}PuUfKy zIndzT8`t1%z92x>Dde5NgBF5Z3GASkb61j&pTwOk*xd5s#^&1m>x{P!PbuAlApi^A z&~`Nod5j6~sZJ7`F~9p3yguc zoVGhnTFdebEVl`D&zOUu_6mp4|{9@<=7p1*u`@rrZ*C_g4u+1ykgdrWSBRj@h33-@-#M|xvz zX<>bHb!BbiAc~dVoEoo~e#MNv9WjEO--;8CUoBIrOmbncT)Sd^mYM~#ld+`RKSCkC zX4oOE&JHTeCQyq>%>0$>i)$N8>x)-hAg+4aOs#l`&0qC%ePMoid1?9n;cM4(1qkgP zj-nviS#&gZFfBo@@~?RPaKnN7ux7|2)d~icr_85NjFM^ zHrY(8=%(PejLM!J`eD>NfpDAO9hshF0&eDu6~Wu;@}1qF#)&9V7IG!o%UTl0>9bT_ z7|PBk1skKiS$5A1qMA_of4H*CsDOlW5g(0 z_$z+Ldx`x~ePjd+!`*Xpa}Eo`PSWxAAsWDxCItO~ghSzpsZdM1<(u(AHZhyKiZ`+X zjPugPTE1FKAgG65uNeZ;c4sP2K-%tPg-oWLhrJfb7lhY#(cJ!(fw`{ncpg@*$yB@< z>yYd^BG)t!u_?ZYA9ULdbj{Y;3s1VGG?*t|$9cE3Z1%`na9}O1gZ2%{={Rzh7B)|f zjx(bhVLXr0Y+^KLogCzo0}hwK+&QlVYq=Hzh3AU9;J=H2!HYq`9f07aBbXUJ$J(qF zZ0`<;>{|IwUQ)ubBul<_tV85nDKvN!xylZk4Rn5b`dV=6oAK;^M)ChpN|b>$a`60* zGt+Z(IsAv2nb}kSkK=eoiT^NWU0;E7GzdTMF0%iajVvp6lDJLM7U|O3?%fVIxiu0J zOi6wDFd{h08^84~{QDrWD6*qkb%k;8WehGQo**RBA;lsXD~8>^G`gR8d7^og|3T98FaRN#iFW?E7#CmmXV6^m0iH z7@<8JHqh)eKSS};Mw_Hb;E6Y2^wCqGj$1PGq0XM7oIs>%@8SD`kVvDVT7n`OS{rxh z6m&D%fkPRsdAPO>@X=E`%~9P;q;Z0MbP^$U{7% zjwH(_d)JHDTDmt3lOVai+ubHfL{dVFA`=SW{GmPrU8#nu#p}!#ZYx(-#@1F|Ups$( z=I*=48)$tmNWB(B)|yZ~VjG3`Ojal%lg1`szmYc}FG>!)V^@tzl##g0;DDjm zMT?+SB^}nfA^AMs^q1q5AgE=Jpcd{CyDbj1A5c}dg5F?s$7c--CC(|*tAP!W5Kmwejz2HNhUvF&aU`jf~bQJUazGw>(D8X819lSl;5ZMMPj zaZ*SC_(uG*#~E%Mjb(0YlK94^{5)#Lk8LLy1m&gb+5__o>($4t@5im{LN88y(YJ=^ zThec2YSgi3wa@$Dvr+7Sg3Yv#z>qj#1My#Gvhm*+&R;mi|2mdufc@`K;aqbO)jMIl zjl(qq9K<|U3C?T~KS*nqE6{#yIc|hiN989D1$HovMFzfex{!t5axQQ869|pkw#QyD zB`e1PQsqB>M&N47p|V0AN!8iP$>53o5j(WyEq`z=j1M%962(BVhr8T|IkMbpVfrk5 z_Obtumi%S#{y#T2cQK3qcHzSG>HdEl&q>VxGJ+sFaE1>dp-)s!k0P3!Sv;DC3tTOq zfJ2_hayCq5$;<~@j$Tb+WcWTQD$3Ajrz7Cj+%WcV2tL}C`*>^F=mOm)h>`4?fN1Zw7PTsk25&kX7leURb}$&NW8o?{i4M-n z@Rl>>)RFVo7golpedzzAC4U-1|DTzj&Eh{^ym*TLcr4GeBma}+yhBX>q^mqJ_MKtL zyA^4lj2qfx&G}@_{P87xIw{<-5Au#8)sry`hj6c7ICn$VCkOu4Wsg$*I?U8jC&3i4 zF9Kajqh#)-;;d2fi)>aX?s9ewch1Q-G7d$(=p-@YLE@`7+#^i=>BoD~9!~uE)g@hs zO+QUZlwOAx7eXAg)vq$3=iKO7rQ{2DTB&PYnnJ!O-V|hbF{EcZh#F{adRm7`xA6`2 z=7{r99e}nk2<7+-;Ms@%KU(syf%^aXnY(7Q_^-1w7tWvR|HtthN&c^+G~nlwY@LK{ zb7-PQNc%N7k=JM$yxh0>x8NGT7mz(EW)9bxBUAH)l!c&z zVXEWHuR7|bPeLMI@_%X!Rzp-Cl8hAIS!zO$!-SP>^VT!LD6}1mxU(Z#_(~jBMx6u& z3OwZY;$%0Bu}_b{AJ(kx!MvQn#9KA8#=E3ah9}2cf{7E`t+=pnM?B7$= z!y(DM<<=@IK%O<+2?GzSO2yx-f5M+7Bni#O+tU=Mq}dHcL8ojqQze!NxD%%Kk*FD~ zL`VTS1g3Q;Q;tSX2KVlZ)@PgM=ax#(Cb=pc84i(2tL3$y4DK9_$Rg=_&U6C_2$+;J z0xaiq!$C%5NNEAMNaj47(f^)BGB7)~H7OR3LKc=Zb~3o`Kr}zwWMh$Jc{WK$zS6Yv ze#qj{RsG4})DfvH5|Fx#B^lAf9Mm7ZqC@hj%@I5b^lU+7mk(jXpfp)^Amo*wkD!qzYIvE_Y ze}bQF(#yH{4>1;gAO2t5!{qSdzt7Lym5=|PJ@x-OmS?#5k2sO}KtL=CKO{7UBOi@1 zo?oJ<8bkmqR&{+kj>c3SGO47I|KB4?TKwxS>5q?_A%9Vv^0q}wcu)<4>*otAw@8~f z2&<^NMjq`Fni5|mHsISs5J!{Xn!xD6VTj@;T9^my%b>}&7b3x|obNhG(8DP~yQGhB zLJ;oZAjI1tsiSq00%qGeYY@*Ne%pj%g)0ZX$81RYaTob9P_l=kRM1J;H`_$)W`4bz z^$9ER?_*_)BOjgNj)&vh#~Rilga-<3R08|}UVTH7Q*Dv3U8k+7RvhnE8>rezNKGJ| zO|pLrQmgjYQfH|NSNjI4?h?|eR(PJOl@5NiODZ%?f@tT8mjzf`utbEm#h(Gp_A)b)Mm^bd%_GXNp=w31JQ~7tE0}7k^C$-)IfNG zo6W$h)4(SlPU-c;b09Egvo12|{#oXL%S%UIT?9cCO&a6yr zLnjzS$VAUZ@je1@KC4}wlUP}C0@4QvFf$AdJ1Qmea@T`1-KXk+9+lEzlNoi+q z1wGc^St8OnBni&s;xt~`6r}M(xE&VPP(}tSrK1(obUq9)B?cYFOOQdX=FNh`HP2Wx z3evtgH?ErHcg59aJJCsk7!oIjm{J+W!9UOal+X2FQo3jeb)Hq5kJWdDsT_?guU3?x z3^g?0=31wg*=0E!E{t?COCuujaFhLtF$)Ie_sxjEgkV322&Jn@yiN3QAV{!qznutA zXJ2?=V`FvQ`b8v+WA*jzAF^;vLuUJ&wQAwS<4#ak>J{!%0w~=0#l@@TdAeO0jHexK zIdT{~vlwS+7=-v!PRL9tA(>2t4q|c%=plMt<%Fo^c&0SXs+7mcfs-yT$I)6Gr@4%u zL#1B+LQa$a+Pl{eBhT#6dEHl6u0T`ktMdzo)1Fl2>SnxwyV1jM&&f6mi_05p^H}Em2ai@!3tUtS&CEKd^M)#^(I$QohkDTS?U-JucVe2;hY_ z8IY@gac%Sdwbh04F@WR%O;nY+s_&$A+VdK0pK#^}C}{BN%EJ8B&82Je_b>9smzM9} zTwI>Ne0A~4eulxU`+>!)*EScfKDfTIxVE{lvV7mt{hRl#I(uVo_?z4gdf#f{@NO!6 z#vCl8dpNJpZ7wZeS$zHC+DL{3lFX>ZeCm5SX;`= z+@UEMlq1`5%o=>&D$1eHJJG{Q7@MktnRdE|lc_M?QMu)(a>a#FQ{>{!Ww9<#)bFUo zk)=0Zi92n-JGnC2U&8!?+~2Yd?E3*bZ{e`!;c|i@CpD8(Q?!K>!U#96Ge&7Nn*=;N zQ}Da$);?vmmPJnpB2Jv(4<6j;59T8F83P z7EcD>+D(xDx{N6Mn$W(uW-MEK?JN^kPK3=5~Md~yKNNLpt4%~$efIPO%%_fSS=;OwayN3HGJT<5i*60 zPpFp!9ge73y%JEyb!Z9ZtG#h`9kPEi9%IXF644;?2wGkRys5N+qdl)K_AGA1s;C=VanGXI`zq;?aGj)S5bfAm1JrgAb=%u;jifFk zQu7kJ4I0XorSo8=L;gc$j zY)f>Bd)uKgbt?}FUD94Ad!kCX4i&%YH{$~|j{;Z7a`o*feIrX+J}PI)JB+ueaS8c> zmx6zg`e2j2&iJ>JRQpO9sU&8L!Y~%PqVK6ZM=luC>{^tv){=dibjFSI_yO2I8xWJB^ z8>op7LW?$&Ivkxwo<(R@tsd$zZ}i4)AujX@3vm@=B#iDy0~D8U$~{$FS3sbD9H6SB`X2I>D7W-ny+|LOD7v#0z2aXe?y zDo#_9L=Y;!e_P{=wHCn-g=MZypmHL(S z&Gj@+NaZYAh}-QrLf048ksl*B0w-f8TACum6kZFW!~O|2T8k?A+=4KbGgL zz72S-@?J+W6B=3#aoUWNHmdP=#FsjQ)JrIOfP`(d(85VtsepWd7an`T(|=KjPETV2 zn+%cd5%CD6IO*$4h&V!6QBx88DAkdMrgI%MpGo~l#hxmDeXd@qEb&Nu2*GFa zR9K}8$F3PCXpQ*j0i2?FzlS5w`ijrOWF;X@!rDg<3p+QH%Zz}cRcp+_BV%B+Z%j@3 zu}6(7N-u6tVUJD)s!HRZn{3yYf7igI`e--scI&OQ9iG+S70M0%dD!2?9XrE)Ktm{_{Dy0W%0zq~OqQMtErFM1t8o$huR z&=#@d@dbuMHl$>G*WA4WZ$IPiZV=6XS zu68C-(v6@;&6r6lwyacS&(_u!ZB<&bGYI>>x_dn=>R2Nc(0e!`Yzle%D2_bHULv`U zap7Jo@LHCH$@Q$lTdG$omr0W;bASxO7gd}fab84N%v>{x+X$nCwBwW*Q=?Z+WrQIT z$fc}Pj9r!nh`&n35NDW6Q++pWFMbg`%lK%;X5QE2~Jrb zC!C*7pzXd$9>e;zmBcr^G~7Z9SC>#mvQ(I&i$ka!HV8J}Ae(TTi2B$xP?Dl<2erFl z8gxRE>qbS;L0QwCB<=;ES_dhtm{j%8?m`Oes4Q z@6tUgelBjJ1;N{bwtImiYiP;dytJ@LNGD{Y0$Ky?IKo9@Yxw?eA*FCb73U}%*13T} zU|(@Vp|`pJz%>x`xd@o(u8kHnc=D+xlPD1 zWwqT1XbL>XKbk~=+^;<>7!y9<3&N0{GZNCJ#D^0LrZn~fCd(>F_tntUB<)HC(8C!} zOG%q=vhR#Ne`q~9yTB^z*3u~1nfPo&znDZz&g5snfTCVNgYA$tV2=Uc(P7`M zu$5lpS*g_Q*4c)a7IIEN5e^|_-E;;I&@4zqnJg}Sin|Rf1It$JhQNd zSzj7#L!6jcywM2*FG#~a1YQSCrs9zVhMbKt(|7jb#BWSYpa-eg(}eI~#EE2rg2$3R z-vgDYQ`R*l>#2a3fe9pwR+&m=Z$LQN=|b|Ta^0@M1S0G-QV3@+1nZK3OZO-W<*R#( z%1By`GV;~EyhRu~HXKZ!Qp{^irP$Wls0rJK13Qh z=75VVuomn6qe&7H@g0P!)vQLC2~6BaV|yg4^d?HXWmR((2yHRiq&NG_7I233?)=vH zaFekp2J2GQs`8aqWmRL8uW)omy+Vt|H{n0AiGXgH3-i$~?t^o_+%tn1!8WBPIEWCI z(2^A-y|nqL_%WeCgjjAF4xVIH1zh-v*dV#jBXO6Vo5Tt#nMPAs^7tB%i6G-}r<25; zgh@TecuWdFOV)!pRkB8|Y#jBC7%fM6p*qfYIw26^b!i&66%ky3@ZcKC?GuHHp<&Hz zVT#(UZ9ixNTc&o66;Y!;F8V=2JX0odE*9VMix$>XdB(QILq+PZOckL)n`z68f0(#u zU3?(kV+(H*?J)_;J|>Y5I=f;XyT`yBpgXZz<-QJiPeW2+tu(tSI{*kX0c9M)YBnp$ zssrL%^PqZ`4gNasGHgMzzij5WU{P(M4o+~JFij(;!OKrzdBVSIj6$P~R+9>b%;1)u zxV4c~F#Q?$A$Sup6Z|1zvaBOHuoXX!&ZUy9HlGLGEiYzMa>E{EHZk|b2_iQz`*ji) z|AORx#a|@q1xXyShS>o!D{`!8ze^(cOW0M;o<$E*-o80656xe@%5Sk?-1s;))wI+? zFe1SiR4T7CIEJk)`@qMJIb}Y|+B5BUL?dG;6Mle}w?ih}iujfw)=b$4zOEdD#3!~EET4P4q1?&~H@ zmukle;W`~3a7l#3+OUY2%ygor!6WPsD~|pYehhsA6526MVV2`41g*d?5OkKgRo+{` zm5F(Wk+CTiO%WQ~${g6ZC1IRVK$)B&dnj&J7=>Ei$$f&YcC{rmV2wCtdaE%p!TBDn zAILn>Hc%CNZSCJZJ;Qd}%;B|xs^U!@J`V9Vt;=AWYNcXe9zoa*kF!MREaCxN{H;_2 zD+&ac7dZ=>q*y2tWeCMRk|cpI?kSAm;T#B5!eOP2NEffuZJ_FT4Ya}Gks7EvcYh$? zaulO%p*csPyICQosmhx$aS_JL`uzyE1BEZ>^XQ?=eWoLdfjEm~Owl&H24UXRH*07? zOmb@8Ki7^0XvKOuP}+wL3J8g;1C2B^%{Y6Qxj zRWRBDVdj$l+98Eun}DuLYBU0!PDFoL ztJmwO)@|(0I2gA^5{(-yCHr|CZe#G>BabV08w{1IX94Va#u0Fyf=4JmF9j~)`9#r~Tb4#Mqv;D--b{(b9QEs}E+HZw}*OjZ3 zrb@-e27_d=E0;qj?}u|nm_iG&HT&|8%rx{KomIC6hM*efCT;3<@LcY<9Op?r8VodY z66`S&?HEeD(6!^lQnf2e)uvh>&KzHGLYR6?agX@i?$(dH=faSS1M|EVhL#?HcW@9f zDc|L$+U$}s4Q|er;%Npp?b_<_){6I{0?VJi*_7l}#F#L)*^cG0qE<7MjV(i^t~nzM zCI8b#We_h7W(}+DOZP-%&kAF^7ZniU_>?n-yg6)0X9aoiGzQWf^@h4#9L{zuZ0Y(c z$~5A}3EcbvpHr8u90g5;)gS6)2lqyt2ZRv;3ex(B#Q8Cyj878+l>sA$+TIJqZP+gn zO~IVqiuWk$b_!W(yPKjQl`V*FdL-x(uu%X!A{YaJ-xAV}dpQDh`VK~GRk`j`V2cLP(M=m=c6eNM~ck@ zin>wAlnF4GOK*tCH&+6unu!C8n7Y2^!W8njz~qaKnsGcY7&o)!;J#MukDQ0Of^(b=+g8+NdJl}A zeN@`IiROJjVM8ONsl4lx_kWWj07C8@fGfa5_t6+5EAFNUqcp(*STAXaX=}W08aAbs zJ&L2+&f4k%@^A-u^lFU#%Q(c5XYSLlBirk-w@XqLNY4EyNHe%0sZh6*SWwT6Ona0z zrlz*)NOjZ#FKEoo&5B{*!^QFIw{D^Zew^dyjNH`>&MFmkbd4?TZ31%w{uemuGuRO+ z=lC_l`;d*jxLl2qAMZtBjJcM_3h+*|>eye#QmU(C{z!Fdvw^6Xi6;5ZtRAS9ea?$z zH5&G?f%B6l`{tJ8uE^bqeKnQsO-Xwh80LI4TxMxWuD2Oui>agKIJ39ZRow-mU3IY; zCms=g;z1l;BWWx4w{Bh`orHLh8jUYqzJa$eV=%-qBs4!|>hyBeEpjb*Yhh(=ar5%( zeOqv&wza&nxv+Be>f*x2(#kUINa}-3mBIwKfrBXB&^a--Zi+2bo~HyslV+9;o*k18A2XOE#h}Wg5rp6G+_w2L&PSUGCHW*z-8;)YmrNsNj6XgR1`M6 z2fCST+UIRM+ASD(8V2oavCrg}If3h8(1sQhveON5qT>SO6)K|*^sB(bVcn`dYay*O zrI|!4(E>lx43zEW2?`vclqiI`h*B&JU&EbQxDuo6tZR@4bW2%`g>nkCZHXM+D2~iJ zg)KERiiQ1r5L|cZ*3FaGP3~1Zpqs<>auKRH$(=N668#N>U4pjA4dO|Eg*agq@8QJX z(*2Gjw9+BbdMjwAlVWvh$Dg`$Si}uLokSoYO>SRG-QzN(J%9;P&>$eUVL<3B*+w6v zA9>=tsk~`m0wN5{Mh5fU-EaY8N@NF?`$HKk4%*5tSuLf6MKFM4*Iu0L4q6qtflH^AB7f?FTsYSw$Rtdbg4WUm{{8p(ZQ>fJB3`}(?si_)ky2hHAex|ujjStH+Y0xHd zH)TSGDUvsWcDIe#OQy|J4sAO*0?PgwBm=laekyEmG6ke49FO_YgmV<=96_6m(l5@QRQdlAn%2<@tS4jK z^{qVZdM(DL)Wa(N&A0$bWArAH#44lSq&R2?VW`xi5DR;o?pZI0LvFL|Ksh!Pk}>Kx zw}d7s72y?ex4U&yony31N*b%XU(1JT%a6TXlGK?#tPj2G#vMsy8o9J9SN3ECCOi=7 zx*lN(D}iP)j?H>q@dDhUoq>|rlBdr)y4;tY7-eF$6*zmGl|CK07J~>8?6va771*fN zX_%r`u+s|r;NTX71n!8t@Pqb!@VnstBwd)4`s&BgN1piZRCit1Y8vp#~Dg-JKTdkVLFcT1V@Ipoe)r5-q89#oSxK4uKdb)0A#fQ#Vh1 zJ=atVa+v8 z6iAWY1Y0+mx}QYgpr16cM{=H6+-N6JXy9k%ZeiLjxmj=0#CHL5T#f)@%C<=u?-h;Q zV~=m$tPC`}V;S13P3_iw889!mRkuhR1yRNFz&40GI$44s(_|DDi0r1wY1fVr^x22vOy3N(M!$cI9*K$B}~>iC>o~D zES;25Xw}Tt`xZNTE*PIuv3vTHXlp*)!+o07xrKp3G2_-viGU=xPEW5FVZ6Pm*sgA$ ze21$=5m;OiNVkCT( zr1H1P$`E50=Y`--$E}JE$0s>2uI#9~6J&1PEU>y8>&dun8t z=zv~BtUbB3L1#AH+atsT0^n0m8bLO8pX)ihph(j84r>*Hm-d6P3Gv2a)NUi;6X1M%hF2*REDNIBhAv#)Pm934%mr zQ=B1Le{@tL-1r&LCS3S}7QCQ763@+52ndeQaJ{h9;{wHaz;m;5Q|wXtaj1N#UcL$@thJ_3D@iFo8X8AgB}N4_R{juc>>cVnJ0{&x zBEMoG*k?WGr4P3BoHwz!;MA>x<~p%ok*8s%VHwr(v#DN$&ciV@y%#6DVT^ql{*wte zqo@^-1SejL?M0Jv7C>|hlp@(fDTr{2FdVcifS3_@h;6kT`kg9dypkm)A#84oh(Tk}-xdd<;rHG4yh;yyGfa*#hmT1+jwng# zcpVaj_*d;tbz(o$G5to8*opmlNB`J|jy`5yXZu;qr1@A5_Qqh{Oq|BGhc*|NuWw$T zUxQ@X4fDnI`Ku2u7ELp#5yENCbj^>#emxU9Bv?S^`ZK3lzSCoByqR}=D2eBP7gOd4 zTT!%SB3Et!dASQ17n!+_ZV9=tg5Xf0F4>vz14qAXfI4d9j@*h^bvTlzf75Xt&IJ-T zd`jf{nUta3Dg+)pG@u%}fWgeL6ZA*~`EzvhW_=S?PN4Mtk9;B&tzFXRR3#!Xg6U(b zuR4-#%wad3)MGlC8O%vJisQU?YFrcH?YIZ`L|`BX`NLaIXo}Lk*Z{}~Ne@R{AVqOh zlPlI30O&NVV3-fi4Mx9Z;8lh}@+=}D%Z5Os;yay*-lU>u0aVLGdQcH8R=|abUXm9j z6=TO&et~gjN*lZplj zQVq+d#sGt@#0mk@7%lS^qeJ30vjj2BP+!DVkWsuM{raVo_cmLCom3E7uT*C0Xkubz zn+bmI&}{k3+RDnrgbZRxTM4kH6;35GUg40@SO^~nA&NCLF_H1r=dpVTp_w{b#=T$% zE}&vGF`7!sn@D`*nn5Fs4=Tl|F#g;_L6`*!^ z{sU{u@VP;i!nN=NMqr{~lDdlH$%oLX5J$1Sx&!MbDF_KjpfW?W1>>%UybuoU z2;$>Vju`pFJz@(MF=h37{a!&OA6*%_%*1Hsa*_?*h7Q1hp#{%fCF~3=R+Y@w0X!=& zxJ@z514CfU?aNdNzJLHTMc5KGR)`Qk%0u7H?!r={Ra@5rV!V zZt#UvS4eVOhJ*Z=RC@WDTK`~qRE(pb38+@;8a=b?pp>Kbh!!(DvVk^JQ%((OC;{ta zK9m|;|Md=OZ#As&4P#rh_BAMx$?0BHRG6QNii_m!nbOj)ewXy~EbXYVX55b+R{wN` zgSx2AVAliMB;j3QMyUpQ z)iJnhU9g_oAkU)PIHN6zt?(Wzl9zFzFir+hg$uU?A^BsRRJT*namq4Wl=s@6^ln; zZ!mA9(pbSnnqiX^#ZfJ7kykw)KiY;gg)~JUkrqxx=F>ytnL+lGzV8;6b06)f@zU??=ia;6zTmh13E|#@jEfNqo zIYoZ!9^+gg)}#f*E7?IIDx0%v&b^w_5^Qy?Zx076Z9_;)T2LW@6?x#XjyiBBnp4Sy z`ka#@7MeDoFBwZSdm751PiF>8VOKD|Q~|&WM8*Q**5RG}q>dx7^|xXJ$Se$YiFL(2 zDJ0A~!Hk%7rMhWUb$~`#?2$-2M@vHNI9u4zEFm!|(9?o2RBGzImJy`%kjIllfRi|@ zN1m+=zaKlXFK zJMoT}efIf3^rG+jmG8Mc|I*uD`QnWizHsKrH-7Hxe(b%kdFlJ-W?nq;;+kfS$`k#Ku#P4mm&cz>l-`%f#-%tPXcYnD5_K)2C6=%=@WI&t0 zJ>T=`?>l?t>9NM-$G-mupZm^#{rr2rY4)Azx}t*tN-{Xe*JfQe|!7a{?_lT|LfU{{*zz& z%ojZep{K`Q^O>Ky_TK;a=C{6bWpD2TpZWdIJ^l9TZ-4T`|LUh!Fa7mro7d2bp5J-t zZ68WLReROP{WKJgVl_T2A#-%EZY{ncNbYu^9LM{oYtcl~dz zmw)c3-uZ&Z{_W+j`u=Zt-mCx9f4%L4Z+qjji~X^ zFV21Nseku_PyLhcy*+-*hhO-_SG1n|gPq&IzW4Y4^H+cPsSCG%$!bhl6Mz1SkNnA(L)E|kWaXc|{I+L)H2U&i@Bg*K>0=+SeDtlgkN@%1fBKn!_}~ve=iARsP@_06At z-+Ny5f~$8t^t#S>{`uE^)qf%PKIgy8{L0&wuKnJx{pCZmZ~6J(c=GbkKY8Y!kNoEM zzWLK$`|rN=C*J+Sm%Q|e%`bi1-=A51>gnD~|Hlvf-fMqtdHU7p$usxNfB02zOuzNf zZ<=1c?bCnM`jdZj=Es+Q`HPo-|B>szxwdiUYqtK|t6p|7{`%+i?r8u2CeFO-N51Ge z|I+`7m-m0+H*RnI{N4{-dh*OYAA0)_e9_9vPhEcHH+I?6=|11C5-@WTIU;Mf|A6Yo}iOCB${+G(nKl=38H~xeF_d_rF^xHo6-tT+Qb2{&O ztpZzlF6~Ze!*?eT>R7<-x7Zy{P7orFZ$5qAG`ahCvN}UxBtLvuYT^E z|M&y1{>y*9^p4M6`I{%t+)jS_&8^S=->;lq{p>$@`f^k~^M{N7e{}iw_xzUQeYZvVxf``imZ^t122`=d|(_VZV7`wwsX$v1!VN5AfU?|$Bg|K>Aa zcIMCVr~c99^q;)w$*+Cn)nEFazk9)l{>}33fBoW(mrR`b$xpuZ+duTx+h6i6pIN=_ z?r(ngtKRZ&|NOsy?_2)#%g(&xnP@SjbW?sSaSSuM-))xk0bQ z2CX9!27rQ3EIJ|%rx3OQOn;C}=Gg!jjS7ev8s>D4R#)(ROse0l574@DQH;7Z9TqkQ^bgj#zie z#M!1q{z0V6Sp_sZHeptJfy6kl>$pP$91gE@sGx&XaN+X(uU^4}*Z>0!VEz6UO9hoM zI3)xqClV%w8&s_4P!U9idQU%tlY{N^aj}7S8|y^*>goUkHE`I!B(6fq48^U(u4c@B zL`$}JV2UO3s!l3`E0^Gp#GJVUmlTneQ^Vy`y1oKC|2(!snTOiCA!Y*9rPR#O!;2d% z^ho3wsGhNAvC&Fj$f35HxEL*bC2*8h;AfHzQ}oKR03Jog2=6@bg9 zy;)v+uIUu)p|C~Q0zfJh?Ez5lDGXj3xO^ekSKvAyE*%@B0$O_RCpXKdR0r^Afl7&6 zES0>Kn-VlZ9Dv}i;;Mdr1%I8dJ&+LsB(p{qW*8={&Q@l@Eq~yjf=7n_bvorx5od;? z)R9?!EnJ<)iX!^+NL6mY6ib)uEv63aY%Uw-)7YY?QGrz0+XJAx*nl7o!0^?3bo%%1 z%d57~T9^-4J>fIxQdvfz(ioL%k z!y|wQ*8aKO%Pw}1ClcwR>d|rq??8ZLI-a{n607jCTe!Pu`+Ra_Xi(wmY{SZP0Gb9c zg$zfH1ef1huq5`H(6~heQ^-IAD!(t~4#sd{0|*PfYf}9$VFYpk)CNEG0TqTyC>IVe zi0=2OEW&K(C$Br952z5p8GVF@aAowaNt`B>a$KXr0dppdQ|a1BoHW9Bj{~i*XG`?s z7GkLRsJ7_*l+4hdJ3^PY)y0n`b7KfViHS+;h3(&ssOl(DO?JOV{fBT%JvH50`795) zGl8_rBOx|BuQ=BWb}OG0(t3XL)5A=+-XWk0epvNJLCCQ`z2fsL9y8!*D3rj}BsX?{y%tyGUw1Fs_vDWpl>ABP7*)d{$(#g73h-&7DnF(HbHnycoTrxI6=ZzjLi%F(;1&@YF5MhrND) zDP~}4j@Xi2SY*FJ#P1t&>`x&C+#Nk8Fpr!6#=QPPEVX(mY5a3c`!E_gOa&#R1H#@g z0PU)-1GTM1%aza-X;+r;UjUvlxlx29$jJRqqr^nZZy6#TgEcCdR3xjaoOB_RTw3s8xv zJpk9D{qmd*ylh3x@e#Qpgo#fWz!o)tI6?rdyx|r;5{+-eju56;5}k`iTkiD+8IhyI zV{zV?JDR^zc7#gRu`5*Z3%8r>iNX$vO77-h^JCJ$7n9cNdS+m0kIHq+A^jxN!%XZD zafab43#Ms~0+O1>n6>B!>Z_9S%J`T0?!Ld0?n^oENpBjOdM(~C zj+m`HWDUA@OB~?P{EG1&uypN_f+bq~ns<)p5i!MPuc&P1LM?IM;wa zz(J9?3x3OHDYv-tjTgZ*dBluLV?NufmIR-7QoDWPr||VDqX)(|PJhJEbG>!p95rC0 zguI)PS);e(0uRE2e6I{)lb;OT&q4X>2tAz(xKA;z23cv!OjTb|;O_R3Y(9AFH)T0N zuK{Wd1*7&LN(>`o4I$)oE_lPIAB{z43K%bg{3y`%q&ilIgi->Pza3-p{=QRIrztFiW(3_O7>2FzoI9LP-5+5o@INPBPP z^$5*>ks^t;PYrjn=v%4#Fs=NTAbLu?N`h$U(|MA-r< z;M@0aFIa9x`)d4=v5RjndZ_{C=1+?+`L6YI{DO#h@Mn#BA4N_NbWqRZybe6A2eka$ zYg*i6yp(+)utJO=>LFS!uB+5qcp|lD zGnq8g5+yu5L=idACZ}Nwo`1;+u033Z?=pz1`b_+Sq9W;jy`)N{h+@)6Zy{36sV{Ddq4&gW{EkJ6t>Zv@_ z6Jy%E@REMjS3{P34(T?O<@lkqC~`X6P*zg%J5C%A_SE!2$jO)6Wl+i$^lm+*aR(2k z(7WP^`7_^%TXU)5#8gN}2`1DW=SDF@hKTIr$)*Zt&7e>1K2nEnMs4K#K+qb`mZb}4AnlFbPozFjyd z9-|FHt?e{?bHnY_a?dgbaoUYUN<=l9s7;jtm%~TiLyN_ea|5b)rOmJ@dDd+{mrfA0 zUM8;gO)OX&vAYba$|0AmhRUruqC z@_D?KH$tbQjnni%=W(|+Uc;9KTe5nVDY?tm6LTCSYfwqItF@o8NkRGh!xh2o563^=2?_5VID@-2v#aY|}SaTeDYY@h> zMK5+&Hx%?ny)nU>@I+0*6^QyTpKD@3^}an`OljO>lGRhdCRz?J*PG zhKt@?`*Zn@Av$dK&Faql zQ9QSn$lhh(eeVWS4CyodSoCUkpkbIMBwgl0sA>X?xT9oXr;qDbs0IL27~8F7#XCOx zxXv(kGW1flJB)+&-_w4)@foR)eg}K6ZxqF8?VNTj+I9h1@}mJKld6bEFw~wJYl>kz zZON7&_E?POkj&mK(T=M&Xhf)!f$_VG$u2LgnfE?bTwV&4&p3=wivnCrLhWcojNN~V z49yyRW7s(7tMF;K3aTJ)R?upe&+@CH{3sQm+I|`iOF5J8nEdmc#NF`@V!#s; zb`r30_18@QXbv_%DW8>>occ!rIeqL(S9MO{a#QqoOksvlSG+L+5Zs$vND44+E%cH% zsl$O;fF&e1W*5*z5h?K3#SuKD%N!U8GV=23!|-0ERm{=~NAh;S1!U5lE}tTPNf}uJ zDhQ4J&#+nL;uK-Y0PG%Q^R==KEiw%&WOQ<{?7}BI!VH{QOml(@rgUypQ&xF{VUNHX z(~m}$2>G809KVuCoH&K^K6AjLT+u*B?$`6`tz8JMUMS)^H>yc=;2v&}%8*xvBb0<* zsXg>G@$oPp8e8%dXNKa#)4%~)AxyyOGlY{}p(=pEK#W}x2i~$O5-aFi@cni6+wWfb zwE*^#G*T!vB+KjNCQo4I>(&(*WJCq7CD)5dVkYz1|#92I?Gd>_TgUa>)ZEAF#s;=waG~E=>SUZk6`OdpxR#bm0f4;)+IRV^ z`x11uICJvC5NuI;Y#!0l`0c1{O^qq`)>KUB{RYESjsTwth>4pBoBk5bU2^enXO7^& z;TPU<-WO$gBCzFC%!-#L3Q;Y9TaDGj8K*G$jIbhQ34z_6B{w5oJq>@R)-(q=-$W;{ z%dud|Yf&Z&eWa6~gR^_WD-&|^6}X%hD?xxRa3Bk&SFW?bCWbvN%OUGA0bkB!G$0iq zYI8)IGNR&BIv9)Lb}@JIz}U?_(?Q8^*(`8CDVZjy1PSU*W3*f7Pv-(6?j56k_H1RQ#^+^22mi>K~Tp9zIeYu34Eo0KY3(p5o!!9hX* zc}Zd;{DzuKt;LoW<%}>*Pzq(}5Gg2m!w#nOXeq91V99;5A#Q~2HDs~7&g+I7=&UE*&OJQNwEe(ZJ7*HWVO z9Lzf&)NsQ+x5jnA?eNrwAtLs@8NjB2W~QH1zG~?5Z6RL52rI#_)8|Bdj%8E2U`Pl+ zYBW#kYxr=lb?lChPXE~3c=e$;#ixXYUp{9l?*od^^B%%1B|r;5#W`cZ%k<+Z-E~w) zP952v3$0Cz&A>B2IM&wn=MVQU6B;q_&~#eVaC(Bi+hVdVI=6|x;}to7-rdlt-HIIu zwR0`HM~jLpNQ@nEBCDej*b)ak6Q0t~$w;%hRqQZq1SErAGZDAQQa-$d8x zkiNL$EW%BmT`yyna$FpgxdX#C!Ty0vgQ%I#z>uR)(u!$Q{r{K(b#VaQGh87{3lvohpa)SG4?q!C*ay&t z0i(uw1n4nqff9MvTt5>x5s2DWOBvqA>|c2YFtItz*x?}Sx)eaWI|ofA2#6<4vY2`R zrXB#UIRFSD1W+nLfHoFjp$uQ8%O5%Rk;Y{e*vo)JmSKu5+Ws6|3Bbw`0r>sQ=b0c3 zz(APKQTPZEfH&gui;_Ts&^Fnx6IVrm8W$uV=8>WJ9rerTKByqeinc2|1YzXP1bh4p zztC77S@e7cO(CaFHa`}1K+1K~b6yji%@5>b>^__Y0>r(TxLNiEKeELTdt5Sre6%-6 z^O(T-!m1KE51OT#`3Zz6_Lfr*8ETRGKo)=lB-O7-G9oM8-(7=|Cv11=;Cr@@?|O_o zBBC!q0K2f@zKscbK7BM6;5bXtG4(DOHJ`rXBGBiLGbvOm7VA;19AKV`p>0^$jCkgm zYbS$WN8`~ki#zyEd3CJ@Qm1b6hmuGEnY_Z)7eoXQ(RNkSpdR?X0_;;FC=a*G>r6Rd zZPW#FADa4H8VgtcvqCkdyBx@rkOuM*>DFGP5vI_Y;Q)fA^AkgLz&@WAQ2CDW54?`Z z3aVc$aFa!LmI6(T;h}Y|LIY2(Eg_CVW0fKT-khEM75kRT5bKL`U7%k$N@t-Nz0kI1mIaoCS4je^7M!5p#jLpT5=h4p#elJS_;I*pj_D1 zpWMed`Qh>zj>ih<_|S=&fIdeVSfB{F+X@~s%Bcjvn-u!L^1|g0+TO-jpq^qr>i}%7 zWr7ivBX&3dDBlO!GRH^QN#s0xO#~U*v+zfX5&b6gg%wct`;Ip(73Vb;3?QrXN1EGW zlNU1som>~uc@oIbo)W~E3RIvaW$`WwfMnL7V)AGL0%cc2hVVdGy$J$Rh6FrsZKK$$ zKRh7wohKrZopzo8xMntMp5%lFhGd9vRLB}ej*O4>o9rdr6r5 zbl^gAZZZXc&{XKWk0t^JMQzDmzuw&Zi~=B5YQ{Z$a}fU&j2lcTARo7)cdNge1CXh# z87-p%L4TF>ty8Cf9Aiv!1jH6+>1Y5ImLYWLyOWjKK4M`m=)Iwl-A<5CaGnvQP) z#Bjhw-6w@4PNQj(#oc5b6`kMcc~01XW1@kpJJbo>*wbluM|N^b5&}RkZMCKY)je?L zK)##~9X`wk<9hHQ;HrKeFEPRYgaQYwHds(G&4Fw%r|@Tn17P7{;u1i_gfLN`-pd(N+l82pauY>g-VI$FS4bT_C*R-Z+KKX zEXnQ%)lJS$vY!~S0Vt9hC;?sy7uVW~DCwZ6+m!59`f;)}p&K7YZ8wJuWxlUlsrV5A}Z@ZZ00a|EB+Q^YL)~|N8&`6XSoa{{ticOk_9!0BD5- ze*ypiZy}*50RZ)JXivrn002;%$f_vGgW00^Z60Fh&M zyQ;{4_70%o{WC#8W;QVZz@b^GYrASIeiSlsuwyqib@*b&?rG=vul0y{3VGT&+L^f; zQ+wLk+PesOiqigzA!P3&^bgEIOZ_j3tBokFwxSBPl!LPw^*eT6c23%Vwf~Dao0+S1a@X%w+HKAD?C7V8`)~g@cQoljDEJ z{wMrDsF0eOi-WD(KjAg(tz5;pML7Pq;Q#I=F2lL+x{NHE%d-pj0+xGpB+Hm|wal}wX zIR0m$#Za-NnUes3>&L%ZN)}HH5cJjm+;(^0bv!PyYcb#xNWaG}K?oy+KR9jf7}U0@ zH#yP$?QY=n`}CBsg8&QAE>gwuO8&Wu6Lb_|oL-3Y%G&6$QA+qvDa)OzHMGf_vl)%*9v#9&P`iNoux<9A2RHrhZjd8Xbl?Flr0 zq4*Xd^vVQXJNg$!#c{TWUh}EV$t(#?hc_cm4FxW#&ij_e7^#t?`5dG? zE|>1dVzx(r@Tjj9j~q?H;VDM<5la&?%~fS?P>}z8)4t>f6Bd2{8Z7Jo@(2!B_6k9V z$cE^K0co)Mo_H8{6pUW$Qx$PB9x*WwFF(iYr}!{*?MlhY{JQhI3N)IFew^>p?Y%uE znc9Pv>5&%$1{fcU&`&mTtn-|oZ_0WaiR+j#->wT;OqS8#kcPLZ7eP#h;aA-2)z5!^ zCN)M%8ti;PqpV_hP4gV+5M8n9+YJo5u};B1Z$ z*0AE|hNLLb#ra%3EWUlvD0Q1O;n zZMnpR#9)|n?AMRStm^DIGCg!{GsxjV!&-YO)zJRuxcYh^c}qxg_O`IR{IU3Bg4K=*R>* zJF4ZNS^K<)G-DZZ?8aI*qc6?QAd~WzFw`ywH^Ci{%q7YAMqsSK_osB;I0{rX%WQ78 zSH0FaI#rJ+>7Hqx@K52tAhpYT!uqUzOzEO5TbC@tjFJBcJ>2|hy0!Fw@%ej%igZc4 zwFA@03XjRjdD%3p=_mXWU-)gUYjmakGQa5qmiFCQO#j>B!^!3$tT3>#f{8D4yeoVpMbG3fueF&>&FM5q@nwOT=8G9LVP)#&fvwKGxAJ_-w&g{PL3 zbThTL(SDT!I^q@^q(k-Ayv0y<{r1(GS5Iu^@?0vE%fWK?yEm1(k(+Xoc`TA*JbN`C z{r>6`s(okW;WZYJobTaY5@6(OPNqcf1j8*(R9R@=Ea`@@UA=`w>P1)mK0_xK!ypD8 z^5O)>$}nX?9@8x`blg>7Ny?;Bj<#274Z-5|A2Svl!?(o2Np_?NaK*q{WHD!3Lx0Al zmURN}d#ZQE^7>INry|7nN8};;*ni0mfECZHg>a0UO!s|&1G)Y7!ol28 z^vu;h5G;*d`WN11Ydye^FNqzmGcwtYWAuS%0NXE(KnpbEgTrs(OQOAR8ZRPEuar2S9^ra30ceh5uC$y9UELV4W2reKUjCiS zBCvUpsiB2P{jQJTQx^q3hI-_lr(V<5$3t5)+e6^0qrYQj|&LwGp?_HyZz{QaP5 zzQ*|G$LZy{oOu-jV@NP08Xr;Bz9BZB@&GlIH1A7BpOsRB5HlgmB-FXE-AYWvW+X>p z{ermc={QhSYHdL7jpRL_3AqA;>`pfaP_RxU2;Yhi!zvK7Au#x)t{Vs-eB^D8Kx8|~ zYM!o|w=a?D!j;|W^t+vm1=|_4uV+3qZ)SRH6mz~KmSEz+Ru%8Mt-i0KRCv1cwb!V` z6y^vxiVd!MS=6LH#qNb_P|6bc-#H#{-$y9X)las|#n+oinve^|sw;5A$&%|ABODia z?VpYEt0?NA{Bz`aoC)vlFOktq?}Zs#|6B`7kbSy4H9}F!?h3I9RKF^at)-%BCb9IV zkV4u_po@umNBt$n8mAaKk=>oR;6r|+!+*|XjD0;|3ZV8-Ueyg)#dTfg{V=+2*yBhZ zHeK!J5OBSURvs{lc6i1%@iOj0B}Vn;tEWGVe!lCbpVZhKCUR(y>>QWe4BxQyPNF9B zP~ly%ktD#b+=$;a-}~MQnZ@xtk@B0jmXo2D+gIOg4IIeeb~z{-o=lcPo&P&<5S3uy z->at0A2B~$B|r>ucR3t>g(2lSO+_61wqI6VcV+v^mn)hlSr~I8%K{Av`vQrj3s%va zq}2H{r;niS5;&;%D@N}&EH+cF&-b$tNiQ6)iUN0#jyl?sz!z(;9(F2Wr{0yvIC)x0 zSbX0r+G|dSW0S&~X?FKqPafk^`I}JCa*u~z)briVikH9dTl*M87qjmMw445w5j?@{%2Q@)^(0k<_QCY8mvZUfifB+SD@w`>x=>ODOhKKHw{oPSmqX(| zkqh8FGfZMWjBh(FUHJXc@ zv#U6}zU%iW9ELwCWNZsa`|?cZB7Pvn(#%dQ{-|o7b#Y2p?x%v+*%RxAT`{(Ck=S#c zuKFa4nBf>_oO-gMbZOK8bWH^LD7~Ee;KvhD$L!RjHz*jQzE7^Gwf%^6(>XF^DPt)4 z+ZKtYJ98`AnE9)6H)Yt+=7d*qUgdFeG zUmoFh;=OO420I4>3iBk+oa~M9mVPPCjUnF&g(jC;(Q_thV&?GK{>jPt6h6zx=RTSF{>73s=Y_VRy-tG;dadwRKZNy82$ZwdKRnU5i#YW8GpJZ% z9=Gcb!yJoGsTh*1sq!{(Hfl^OpnCZ|4_#*B81h`duP%LakqHh0;hJ)3(9>N8hhhJ4 zmnGQH$?^+{T?E?5FH!WwZnKUvqo#MjHzlKKBt#8psmEW7zzKnB37fJB!xl`Wp--#p zPJZOOc)h<{Y?tzKE|uhhMO^g}ax6j6 zGE=0<8l0gSfvXtNic!#_FaExVav+L;5sq#@XHA+Mopm*t*c^!jI6L$8h=cD`cNk^R z_C{JkxV}$mUA(9cMwAWqGZWl@z!AkU0cTu{H4UJsn!%rZs+A%4ymG1ST^JWz0XyOr z)1+Ecr4$kuSEA zY^FHKaBr>Bv(nD+1c~2az?FR9tb=NJuKu`<2r)!8oBk--%p`YYD?D}NM7*S?fh6Sn zBNStA*n^DUYa_=ePTp4)H4+tzLXd(uE2JpKyS2RTt5D&=GQt)}aLVU=+qxc2)$O9P z`nZMm+h@)Kf%uPP-PU&>Tq*B!we5TfC>yC%{2*u3*h4&)RWIV2wuy5y72p*fTkP0x z2Z+77r9b(Yn>%3*G+Y@0Ucm_bwqwUO{HM%uyPUTy=zjF;tmoRyA9^x>=u(M1*}s(#0E|nb}lwiRrJ>$eGvAn z8U$A_e6sGi&-ax^m-38hcufETyU3N z5`Fur^oCvUdHKU6qf*KaeLSs_*0Q8x@`BCspUbz>W})|LwJVI%G8R`ESQwWTs^>p{ zWaN&Rte|oc-;D5FfzHgF^YW;Ho zO4g%t1T}H6`^lm_3A?;7ACj@8@eXvNdNNx(9R0z2yl}Zp?kH8u6Uh^^K={hnKFygI zCUjUg>SJ6bD@@I5EYN}^#%$!|?ytRxeAPfTPMdhNG|L(D)TxLsJ|dlVI8YJQGgkhc z!&I_@U*Xp^>->4G(He0?v9n-P{m1)7k3W^;W-_sPWoBcqer%OwkVsS$4B2$$hD`P` zv#*92&8`~UZ0ae;hm+S!fl-Za^6Int2l@eX<>%EZ4IsoLxL>S_?_seJpO*xV2x9>V%gkq)J} zuqsXAr?IZa>Il9DM#tiJH*rp^I`~ja*#S3uBy@;8X;35~CUd4a6oP|zm*m#&>^R(2 z|LVyCyTMOCg?c&|{ZIpgml`S*I|J?XKfQCyQSZo>Jv)J-4OTdq<~sdHVKWR*LmAS4EVVyeD~|58++iv;OOuA7p>f@ zT;{HbnT3Pn(B#U5u=4MJ2o^kgi0g#a>%QqoIoGZ&OFMh3;H7)3Di?8c^4%^S33UrbB7?I8Rz5-k4ja9vlD{%yZXoq z6Jqm?`4dIW=49SwpLO`ypU4whrAogqJ`s(Ec_`%)J`RNh=d#9)j=|m?U)fj9zeur- zXTHTSM(MJmu!nWAq?2kuYktku%X0gK|9xonLXFv9_<5<;Nkey;(yU<%PLd6T#cz*G z`&-}+o`o{Wt^BM%SlC*tkqiy@04@wkLz~x!{a4iWophxQ<1rz77b4(VVr%;?t-V$3X~^vw-o$Rc69nYY+AC> zIcQT)^tsNS-f1H;mRy{L%-DQp_h)@MHawbsnZeWT(1v35 z7iK;*-Cfm~v7&f?VnyP;%P^k3Z_pYha*P3lofQk&3VnI+DjWXOsoYIUR5G87V__40Uug5z3Z29Gfu$v=nmzki`y@P-Ry=`DZG zJ8BsfYAkoC)-NKU^B)EYrtZG~TB38w%SPFeW1z3!Ci*&y!Wx^iUYb81oYfqqx+2Rc zt)AP+8A!F-=C%h??4HIx4T7PdN04Nu-RABE(RS6(TI}lu+(D#_OREsaUGI9+M#r}M z@zqU2j_cN%WGc^lI-4YVEeT#k*oxFj3LXNl+4(uBz2Cqv?5zokxQ}9aX|v4-GrPTD zb?LiA1J}gC{(te(zb!)&HGg@uJ15C2+5fdR#$(bi#a`;$;yY+%N(nXIS$*!Vk<2Q8 zx=V3Yb??YZ6IZi&zwt|akdk7~0;DCwi}4qeY9MYbYAbH(Mir-26_Y5rVYWBmO7jsj zH@{+1vWjT1mp0t2ihoqTzb)#uIJHzJ2A=RO+T~#yZxf$RsEFWPeW*~iJ)4{v{E5r( z9)@ymDNW8gW9qbSkbz1bNmxdjd%JU2eVFDQa&1@;MVkOmgO_9Y`pc6pwNPiWO^Z`p zW+o~BKrqrEgpM;MtwK}yN&5^9wWuRj65~lD&Ow%$PTzdYK-HV@JgS(h0qBKWn&yq? zjTQ3$8^oHG!MlZZOon&dH^o`hOFQgB^iBS!W*x88W;opmG?QdCVLSEf%W8A?-(q94 zyL$OVX$^jKE3*Ntp^Y%ioXN>trVL(lhWY z$+T`Ws+FT1+N`nrC7CI#J8ZbOp8{XlE}dysU8Y73zQ=W2ygF@2H_s&@D_=IFq1vco zlX5)ue^6GT5I1VGw#;X%h+Y`5k?LWP^a{t4R1Ah6GNsQ<-OK5~^4g$ya*!}K_MLRT z87}a9Hg!B>7mShW8xljh+q_>yN>moe5jF z=x#kVp=ZKQdBe-{JGI}g)Oe^Zzj;JnYLl$t9pRXnAX?NK^eY*qVASF`L|tk|-b#=1 z>t$QHJD~7g>2Z$W1c|K`Vbz%OiGq;}pAx6r%T~}c+FoUNDzK5|tzjsVY7}W&KR+Y8 zsogr&9}?3@S1{uu@G(W!x8(D}{WARszq72peb*v|ZVDnR_pe!|$plU8w?!&aK#FrF z0}CIsd`MrJG;+49=naH(z0bhQ7?M&D&MSV|t|!ZbE%$shnE5B8y+ne^BvJm@5z#zq=W>sWDZq z7lz}{$km-r5frpjf49M_+lP3Z35TUEb0tv5RsBM+2A!5_J&Ymv)6Npf7%NtPfnUYg zW3fRj`DOEAOF{P?e-Yb9c>SI@3G4s|T*am7MpZC`#EAhxoVi;n5$CXDtZ{=YCS-Yq-xF+R z-7JYOhJH)hEG_KFf(i)t3~$W>`t#Po|5(m;ANcA|&R4Q;Cy+fNwB<-%gYWd>^u9*t9YZuIbay$X2P=>yseJ|K(^4BZLwjO1#Ek}` z>aJI64eJbRs=CkJ6Ybf~my0pNTHmTRf*$qTorCi}K~Q*iZ1_+62w8ux0I_ZG+G>(d zLp46)Wr2e>y_t5BbxY9&=M_~Xg zIlZ=f;FcJJqjd6f*V+14UT1x4r@36YY8j&@x6|nOekvBelp~ydG4E@kqt)Qyo^whO zZ(1KwdB4IXqr{r-ks35M?a z9niVOdOVSdL}$1tEwokicbF1uNb3P^^hBNZ#L-v%OYN>-_j%#?w%gFOtPT%`1KEmc zzy0#P7ouiFq0tjvcBr7Mq}s>h@|-%a04J8VBHr}3jgY<+=Y_jj_91H*>xQslYRh~v zva1H_nzz2oe^B^6Q7%UM)Fj*6h7i#2Oq^9j6>pq~Z# zs>@VyicJgL(xb_a`Dtc@qhfc#r!G6Rv94h0$BBIws)g*gzwHCyebF?M4K{{9H`tR& zYL-sqs8l&F?&`895VFSz-`-#UoM}{!F~Kov1Gzj{3`NlxK-P9S*p=Dcw_AF+~7LU3UH++Lv9eeubH zoo)S{?R_hBM`lta{OzVbr&{XY>8(Aeflh}9LX+|1X@66WRRL;4Rn>2Ye&2UZ(e``O zbi#W%w2<>MW$V)Y4$fhNM+Um$t=+Z9=f_*Bw{`mWY+J=Q1d6pBgdX-c@5S%G#?jx; zzAtD!cqvF)IJF_>G`hRuPRJinL=7P3c1CcIAp+eC8ZGd~mlZf|Hl%)i&sK!_;ZXUi#`&ealUgDaI{0lb z;mc%DU}(1+l}G%Mc8g+2Qovev%dZd!LJ)bU1mW8?rC*~l%oN%ml%Y!N%LCkt6CG)h zijK0su^%G_j3XDqAbSPaul^bQ35Oz|80)s>S_&hbs$Gb_1!Wq3vkP%Z_Kjs2kl=vF zjx?9cMbuZH>!HOU75;*S;T&|p!mg|jC+79Aobm%niCo0l{I%c{jZ^o#kDFt0 zrM18Sk5f?@H21f<^v@RJ`rTd*m*PH5ug$LO5mw+t##=IOtASR*BfeALt2?WVhM{-$ zKeC-&1~a?EV{%pk_P1Z8m@p{b;W@fo{B=8oPZK)+j8eC6VZYqoZL?NSH#`}5;E{DT zwo@vJT!*|g^f?_t;ib<&$p7Yb=eMA|rl{~98?xdZ=LjmX?`!eT{-H75F7MG$h2NKd z*G6;TJ!`??%2Wcr){}vFd+hoeK{V^hK3Lfzu2;vgq95+q{3<6TP)%a?MR2W<)-lE0 zd_B&D8TB~>>n`I+!s00}u!X3D>xNRN*GNBL6BU9l7Cqi0Q;7P9>8f4nl}#GNo`@mR zP=&llZju;*F831C2s=}KBM5l;v^&w^c<*g{J6&u8eu~f7W~{;aE-@lnI3w#VDaw?K z4_77o6o_{>;EaXq3=u_A^iN8m!_u}VYc{H?%g6#LVOK*&tmg<-}3V2>_{+{28P%ZA`!N zN=%^MBnqfq3j`Gtp$}`Rm;c3$^|nI8exbelYSidi8t^Xr@|U$kI1*Y87-o zW)*2|L-XxP$z>^p;I~h?eA&T$gWFU2YDOIRi24rI6^oLZ0qGzau81_Gh8)M55WdG5 z>oiZq?IMvNYdzt^i_q|L6N`)L+)0V+4Z zaBSz7MVuGWtNx?H@pUB9g;i*O{PkFB1iuNr>3Tox-+518H$tZa0bW)D%(L?jtj2OQ2W3hMl{jOg#iOkVW6 zb0{}QaOwh|jSBftxZDs0B27hqUtu2cpM{OfL#CWg3&pK`zZO*=w=AqxkwkQbl{qRg zbm@EbFkgr#bQ!Xnv!55ak80ZOHl)IOoDo|AWTl)R&UXts@#$A^ibhAV;28@J4~%`J zR@%-?w&70fnc{**~Kv;D;|t zQ*W?`-Ccu!sv~-wUb4KAvN|9!V@?Uaka0y;CN3R8PPA>sXc_5E^6hjEU>H4)eK}&A zlTCbKw>0n3WnDB;?~P<`M`0ySf2dG~wQ|UVqJ-5_sE4KpQ23ooACmMx1^a#s$r^lz zO0Rm484~D5{Y`q?d7!Jx!FR*W$To4CRp-E<-txd3>d@fMHSywiaB%e0>(cFWGPFYV zu@I%ZCI8n~^)(Jpa>XcZDI7q4XLjkG~(iUNq$eZ>o7FU0VmJO*-!K7 zmwZH99kCv=`iaGB8dk^FLBwu`a#x%>!of-F>aQs{q3%z|h+|~&6syuBp?&J9EDGQ% zD^Arxk)J!Uu5jZ^9`h|RcwRTaAiLKu+Pd$TKb1!-HE*fJBt|+2@(Zlq*!}n*dgsgr zI7jP*@1A_QI>9ykF|j#Gxk6BkQ;PP-RVDP5lU33O#w~$FF>amOOA;Fuk zcaX?4z*vc`+C*=w_8V;!=E~WxV`+P7q|GFkoW9MZWC7VIPcrp{G_$dRdro1^Q_cHw!R>V|rbs%_d721;>GA{K+CpW*1#n~kpHx%QkY)s$% z{;-B;Pi;Mj=)KvMr4jBlm+iXE_oMBQ2)llB{pVr4 zLuqzAWsPr8@BdU5=_%of`&7_v$Jz~S!AklXdQ2RDXZOm>)2GN z(!eJU7qksxQD;m_`;wIC%bK;bZHcXNW1ROiOpUKDbn1Cf_+9i2_RGiq^Z&x$m%zzU zl#6o;wu<^h<$*vs6G%4f%-%^@2(a0mBrAKdy9wa|?)G%o%rxognsoQf?j+g2cpxHA zKs+8OAnL=12#P*^-h#^Ef$;DE6;BRD@CHRu;QyZ`A= zufF=u|9Ae?PapoFxBvcUS6eR~{`e`sedGQ|yx^_F>r(4Z`TWLrt$zI{PS(~R{q)^W zKK<3(@7(;j|H0*V-2N|rJ@cpk+40|>dwlqLuRZW@58igejz`{l+I3Go{FCv6_rGt) zlUF>{e#37{TVMOcRc}1@>p%FxSI)il$E$vmIrgx&*IobpHQWFGg*)eN-{2qq^P`Xd z-;=Y`r#y&^+iz)m;aC5y*Z;;PrPl2qx%Hb5Uo^9}`il?z{(=Y2#nUfddEo6dK(>QAru{QKW>+Ybl#xqV;n@%3MxEMEHPvK>#hKIJ{I z;w4wU|M|&VzPR6o-#F~CkDN|^xTd_{c^@_&KKHDTzrH2)_?Ndl|AM3ceBNn?6%L*{ z{Ji~d|KaBzxcczqPv153?va=N*Ds%5MUH7*`KzZMId;cA?|jMh-7`0vS9E$Gem8DC zZT3$u`S$v2kN?9%Z+XkaHxBvL`R80V@IN=cZ2t=<-h11~zrE$@ht9j?#Sj0_L(jYC z!lB{E4oiJ!bCqH?|jt4(;{C>B;aOH=~PNe90A%pG_A_G{?7%d-dn zwEr~k^|#*pir16NKl!`s@^9Ps<8$}E|Bw4!=>ES;PT08mo$W`x_$B>Moj-iw5B$G8 zeEDOq{Mh|}zH0SvfAX2Ro1VC&<>tHY`;7mt{qFhwHt&Cb`ICo_d*+Djai6>PtXF;H z<-geS=c|pEuHJIQ^?$zS1@G+L^0_bE{DHQkPTcQ?ADusY%4?4N^s8TVJvl}H)6i9) zxbcqj+N|YA^&DXR?TB7~``iEUnn%t&>(XN@Yac#upW74peXI8za?vpdUU_k8?o9llq(o$ScIxcBH2cm7-UtDE0s+ zZ*IQ)vC{{yIezQ|UdOw)oR@Qcyk`0jcWzIe@GsXNyk&gztH1p28_EY=^6Sc_{W~sP zxlil%XRg2gipo)I-}C7UU;n->pV!Z~4}H~1=#Rg?;PE${dAxuB`~LpHHw|ZxeWGpZ zyUT9$-uK`-tLtUY{O+Q)8*aSex_|xOnTHSk%T)WS55N8U-%h{XUGu%azI)}ZhaUZ= zTW-GfdB6Y918@0lp{;ya*N;y=bj$m<^*{91b$_|(CvQCV4R3qnC*N?&JFYp+{Ommw zTfS0y{2d?rxcADI>9;>H_v6zZ``JgIy7c5j-*sj8x|0+4UYyx~+0~Ei`_oT+`4tze zok5@c?%U3Lc*_^kzfW|%!~mN<@omxU#lOr?dVUQyz|%ByEFU$c={vH{O~n9 zZ#;6@`DeZR(wjd0+Y|Ts>wRB4as2k)tFHRszCZoS@-44>^uq4_KKG}ir>;H(pL)zi ze>(QK9p8HLH{ZQs`G36b+buUQpExXY>DU|pmb&VXcj8ON53&aCZ*Q62c6k55f4zO< zS8qD)^Ru75ZpBkCzyHi9&b{H{cRg{(_y=C{`17B*WZxg=rtkawRmaa{-u{!+r#3x! zoA%kvm47_qwpaZ8%s(G=$d#A=Dfj$+U-8PxU#*?({OI@odhrt*x4pLi!#D2x@uQDC z;J^N1l?!o)syS?oi_m@8}-}|MT_Pc4{v&Qdz>B$?;z3}FDOgyl*e8UI+ z^qW(E^rB<#IQr;9p;&n3LAe87)bowX!RN0&`oB*4;Oh^`y!y%)pZKf0zWVO3KK;h! z7e4fm{vVgGN*+IV$Y(YllwEV-$Q7U4a@LcVq1hj%pSsj~*Y{g5=tQeeO*}K#_r6!Z zghwze%@mn?JwNt+Ml`Z^#?xitG6a^Uw>5J z+`bPaZ~xXq**EOm{`Nn(2b^@{cQ1U?`Bz&1IlB4HBTpBff7)+Oxay>tGv4~~$6j^X zo$tw=_WF+g&wlQli}tz5eA|&n&TW6)y}d*CuKGjf7sq}0`13A5Xl}n_Kl$+k?;LvP znG^mKPa79svhTr{|LI>l&wF0~Z11~|Jo)qQKj6&CWAE1vKH{8B+rEGQzTf=R9Xqej ze!cIM7k%pkXYKczYcBrw$A0#+FW>ak^nEuEyzPCTyUcZ3-f)-y$WzCibJ$znbKvWL zvi`^?|Nh={4>^C+M_%#j=@)U3=tJ_mH`p&N<@1_w-!*g4NDXzF7X-PcE2vbREGtL-1WsL+4#mwobs&%N^M{jb~q_ILax-FMl;H{SBn zb5BlvXXE3S|Mc1itA9J>s&nuD$(OvNAAI0d?QM^L^^s2>_^&@d{9faQ!yidpddzpe zeZvu7`0P6$Y}f`_Z$fv50p7hYo``vohy~kd4 z%f)9~r%bFoZNK*&`gnPti}b%geD7_a{pJU*d35xOFC9EF_t-sWUsieHwl9udy6S4mPNsrw(^VzP_YcG4**RHU-snBf4%?rkNWGfi{Gi8v9t2% zi=RIDdzXKD_J$uF{P6?MEN=Yh_iy^oWi5lpo%4pV2R?Pg%%T7BuJ?T5W#?b@$3ADw&0*AM;dr2{8#`1%$1y{xUH@`wF9SDgI73nuRP{qH~b zndEo>{O|>y_NLCSKlzRS_vnN7oxg14@W&7D{?%OO1%LeR^vhp+Q+4KtzsC0*x#Q}# zr@nUXS+_p($N}fy^5Xq3`oM`FZMkUO7w&wr{KpSGnY(-A2?sxQ*wtH){N>@_|J}iZ zZ+`GiFZg}xl2@jmp1a9;*#%Gk^8CXO{MCj3vi*gZ-Do`V((Atcp|fs!M|W=3Syz8z zg=_Br<1hWK^xLoW?0a|rr&8ImFYfc1?_FF>e(@{M`_^Tjf5Y>>`InQm{omU@_w}3K z-c|YC$she%^#zx`_QnU>w%mO|*SjA-s`I=jpJ+*sUirln{m1Wk^#^lDB@fy3(AR&l z&%>8LcKXFvezM)VMPp@zx;~Bp7_?+c9tLe^W2TU+o!*J&FF*o z|8}1zH$3u=U!MEwn-6-pbVbj~Ti$o)(e0PL^{(%{_D7#7Kl8|+P8hxFnr&C^`;Ggy z4ZiKbgYi$!f9BtB{eQ4je{QRXq>-)?fzWLa_*Zz6U_byxY!5`t}4}ST<^nd;O zfR?w8dfPvD^SUFC!JFQC+lPL1`ttXB%YXm*m;dF4KVEdx7m}wv-uk_lef#|%uCBbQ zbCdhBTSspl{rdPrcOUaaOUrEAM>pN_-t*t{{a0Ml^J&c8683*ZQn)2dcVzec%X41% z)XB@f;J@t;pYBNPv*djD5A-zm|6_rQQ$8-1Y~9CR8_$2)rle#^`z5=68;$+{+PivI zua5Zt^{j4RivPPP&yF1_)V5MY0k^!`gibvCHlKc$d6j2M)ey?e8o0z#v{??qv%ZUq z*sda1cQG<7*C-b~Uv~`5bC3;;qLI-_nX;=$Oco#8@}M0GvX7-}%vpJv+Xte0Q-~$v zc~;i0BD3n~May7`>o{&EB4rk7o+ktV=oW-;uUI+G;J)9nq zS!w3x(q6@oIU;MT^PIv>YMZ*RXLS#=G+9YBz<(ptwJO+!w|=#Rdr>LxZDX0Q_!x`K zT1hlUJU{Q^iPMH?&mEQ!0C~P^IeA$~;59QdlP<9e-ZmS2D@|f}Z9Fwao9FAkWwhB= zwzMr}FmUODU$m1$gX_jlOZAVAj7&_94~}f$pjoEhUQ{5SzgDE$HM0$S4v7-h_H=i3 zqOynGwE`jJd3KSQcr9J!Ru189aWE2s1}4zlTm`#UuA0h~ZJSoYwughah7Ru>6V1&b z+B3*aKjm9ROv?V+RdnNPa)?GC%{n4Egl)_+r$TxKHb?Y$ zA+GN7MS+L|cuMpDCPix;+FA!q2^2dRMZmKq;^AT9SU#b2v=>1JwcV4$;n_U9&i|z< z-EEd*;#usb8nc4U_`lU%oe} zdtukBHoauE;aML$9wj57jCAu9c+fCbp*7sbCw3$w5gO3Nl zcQo(!Jnn^3V6%%IeO67>_Dn3Z+Kwqps;HMrmXr6|f>J4;q>K_ypW{Ia-7vy&Re1(P zo<1=J1ye=6#2^%P-zbDhFk{JVlAp5K9U~FFWNhwEbJDF|Hxe4X5lz{a=VNC|H%+$} zwWr~~UbrFAk&OR*JpEj9$!ryb2XL}XnU>pNXF+MsaRqhQ0H|55=Xd@;JN}Ok;58zgDm6>RjUg7US6+{NFHJ1xx&2&44U`|6{}_hAJ&FhD(g$KR08j%Kt39XV|O? zcImgZhqAJD#3|pXRd%*FVHfy@{%2tqmY#pI=UMT8DKpzv z%1;%tdYYC>bK!NgjVAnGXM0C?l>h5mwG{t#QJy54JYy__&_Lg0-@3kujEDrfX(BU@ zl&5cCU_3K1fuhfFW^&``0A-63HZgQNL3v2Z4sCL*S!9x;ZaK&!##ZbjLuwN}L>#-S zK@EhEZrdTC(ckqR&v5l($}8xp&Yo3T5)F=3x)B4awAHIo#wZSM^mj++Y9O>7ZC#yB z+FA8%+Uf1>XzS=))3iT*woPW}McEd4+SMV1EYyGnZMPL=t4IefjA`Bc0@jkD$|cvT zST@e%v>bW$^Fl`6#phtdmmO{frry9V5KO&s<6yL8GKnT8`}$8EAKik6M+XMi4`v3m zBpQeB0L~!}u#(`QBbpHiRJRGvI<$(>w(N(M z3LHQ;Lngdx8dMA86j^M^gH=q@=I$U4STC}_k`$llvG5K0mdD7+DZpR>r`bS4b zGX2m$)HgDK`Zi5&%#2J9vOe$rE+8Sv~Cf^Q}p#5q5*RTXA)PRkz~m9$5?HnTgR&D2Y#K3afwMwDVJS!49WT-ub@+M&JBGk#4Z;xH$BsmD4^!;ohgN&x35l_ z*_4S(HmMe|<1^U+gEhsBXy{^E-P1n2PMaa_)~O;cqP3`F)$lrv^7=k@bjQF`>bK4{ z!|OCIp`GHe7+zC;wM6HzL_BMDPt4Bgxo;`f%wu+ zgPo#ZWmL%WNGmFu)#Y0JIM~Ki5qln(?X5-2u`{)4B3<@#YnH<&;$UBQt1+LPauK_h z5%YyM6n(96{%gv|v;LHab=N3NarMbsw7is`GIU?JNj{C8ylr^}LD*qiq9H2_mTqG% zwux@?j`BTQVlSs`C}gpYl=4%aulrL{sO~Lax=8%vJk9xkFu`?nyG?f-!m_-0Z3S!> zQw2h{PO*a*&WU<$G~xf-JKCf2zg1nGtCslx#dzpMroBQNoy%TSa&gLXJYTo%R{D3j zly`L#Yoe5knTjY?BDQ5zd(l>mOH14RANYCp``;(7p2v*{K-2x-9nJr?s;6Vg|7%g6 z-Ld~w7%3Cm*bfRgxPsj!3h|tM7O?-tmwEeril>?VS66$~{=d6()zbODC{M`vme25r zUIgP)<)`9r6)B`xh!k~4&tr34RVgjs(E<+fH)6Xu%-%sMysf5SVz_UlZ$oB$YVwS+ z%+zq-$fmxbgn|#Vzv|VP*^gxezojj)Lwv=an3S;N6|9^u%vhKUPD%#IW#(!8JXBPxPG!*Kn);LiROl6YKCoCxxk`zR znMIj|fO@u7>=%V&0nie|#N?ZW%lK3Tcnf`H)AEN% zKGZYuPN2~*=M?RPEzJI3f3U(mWd@UGqp{-%rm>SFu7PW27a?vxIDrk~m<{Jaz~VI& zV?;xD1|8dS@O-KVr2`0jJl0i9x;HNzLKOlyvYYc*qBTPkS*tG2Tb}P$M=RKMEmQ4V z^b@PX*o5_#lgDn!4exv|ky<~-i!#DKq-U`WNT!fa&d`f?_{d@3>8h|C6FWZYrq%cM z3Hp!yEQJ3f#ggt@%uPGxySn4qKrb2!f12}utGe5x_rIRiOZH!j^F+MughH#8IR`+1fh46Wsi*wk;jsb4|i1`$tL>m4`fbt-bcJ&#E^N?ue zkp$c#b`kee;zOe)(Q76~M^a#6jZFqgjFjb+%09|j*ftpmTlf7M5WJ2~$El>d9ya;V zr8U7r_i_)aUbK_(Tv1k^fdJ~v7+_WoI~8%{;DYQW+4h8)&OvA(qOvJ;sDX3&&HbyxTBs0Mpm=yMQFE z6+n7+$c16SdNd@{TYFL3sl`HyzflDsCFkDDH#x9?y~rusHcFx_AuLpo%GpN0MR?Ze zXX*0GKRCKyc6FOa0a2S(xK$O1R(k{Bu28_jb7$dTbmI%tCvvlkSxJ%W+CqSaIPF-V z;)XYWnChJ{1d`o&7SQ$3G_xmq6^d;pIx)|#rTSx}F0fr{BYO7=L60oaU1}iaY8Glk zuJc`jE^F5z?ZM@1XM;VyTRsApZMscNJ>c>c*k>4|?8v@1E)xrIf?08e zA;_1JDkPVq6Fp2!L5?V0AwFf>Osz(GQK!d3f>8sWaR=jEQ4Q zzHu~m>_{OOVxcXYYDLQ`sCTWxG)ig5jvZ)QnfMqjtE3$!o$d|2tVGL8N$cLeh3&m( zLHBWhVX|V`_{e3}q&m`G%&SrPO zv9fK8DjM^5cVfC7xI)){(QTW|jF4LXx$NQ0tmXM?KUpob6P?NaI-8YS?~>vGGxDp` zZGb5iN4o*--H%<}p$O}x{;_aZBn9H~8^tELE7mU~uJ^U?6$wPlSGX(IzUCUaxKHZU zH~KZg3{W;noW~6y(ogd!_FV70643X#fGkI6AiL`b?P8OgyBDiTE?HEhipthPJCWu1 z8bWj2uP@lnFXOK>J_a%h6fLSj&)@3-POgc=^O2sy;W6IfiI z>R{ljmqamc^c$tA1>*UAwxxSG=3~jVh->*(n6^0n0Ws%hI0zuP4#g3=lSCPie6VOm z%$J$PeD!!al*77TcERIig2gXm`U;^AM^-MrqE{eg+k|^$7Bm2+64{rx&So9CST_m~ zJ-7_M5V{g>m_<2C^9s@t=jbD)Ko_#8|hfy(?>+$8P4X>On{bpj6EO1qH6rOS#rv%jwlITHxEICtKK!9X%%Pa_C1Uo~t0EPuCu8HYdv6zU?; z7>zoJ$a5)WsB+Q0ic{n+v{!Md4N~^pLdwiO2k;@3FH&EL8#`soOx-nQEVsy>jTGad z-$HZ?3bGwPTEfl*y{yzDlEvVC=x$S=Y80`r3*!txutq!vQi}fc&4|pS`yB_EeS--}7C)G#^Dk6Z^l8j@32( zAFDc+!4#;If2WfP->=aSj49R13 z#47`hWY}09<;W?$GFgCP?D<|A4Jz4@fV8W4QnJzt9Ijp6(_3zZj2d#!czGg*{0H z6w($JMYf`>4pzku(kr@UL-Mb_u|dRQEd|mMc?{HvT}_t}i1aB1;Tiy5qo8{z!P!B} z$+Kc>uK_;>(&bKOCMwD}Zg^o5ai8ckpyM84Cq|I?zGD#EiR%DVb22_S@p zZ=?9rUxL?$+Irb1DSB@gR^t31iMlZIF<=4aLuN0^pMsU%+v{=ZS=?t==znK>%C~vK zgx$gacXvkfe{^@RUZVet@_=iLC-Y8v2s>Wc45F$@UiBl4&w)i&FF^ zg9R>dnb=mgTJM=%5BnWZTSF!kO;PE%d&Kn7K3uKrMf&HO)mI-~ZV z-K$qE#s689N9F&yip-9& zmPB+Dp-M-(v%LXK#)Xt@-N7QPj90gKQKvf`t#EOXRDgL^nxifCw4~ALn2Xc1#4n&M zX5w>Fc2S<_HeJyU0b??^?4S}cA>BAf1TjQlJu^D&RE1`aa+q7!?6GCuWb|3r>kj?^ z!QKe*VGi~Vf}yFLAD;8GkQ3yt#x^ecL2=@27@ew#nVbL{HjoS6Moi;^4?)h|_Bs}D zqHJK=)}`%fLf&LA!Bvdk1+&$8ZdAC43cU{B9!isZqeONhyLO7`7dB>r)aeG>y2cYw z;&#`br@2iwS6!mJ=P{e#u2K*LQx4zSZ3`&q?5a>_i7A?x#BMR%C!dsvP4d-K;Vu~N z5G3@`i^}1Ogei-(bc^&829O)B)ST6NsnlC*(GRr>_-JOV7G-`D4f;mdCNuoFXCT44te&Ja11<{!1VZp(8)CLwbtYfKE zN@ZkY-ANf1kx#(-s{_2ix^Z-Wfgtwwt#1C$uH65-+f#vtXE(@yySloT>_7I>6MO&n z3sN8~b$Q~}2qFH1EYNiMjFVY3!Ilr=_gpC+NUOKez-pR16>TeH&zE$Qx5Ff227~Th_q=kEnI`c=1dO=Y`JtqLu2_CG9Z~42 zL6{;_9!z8~`7xv*5%f$%G{uS=ehmd{iC^D=+y0Inh?#{&BdJS3HD7=-?qpIV!$&*O zImB{MqAd}-EyAJq>x9&9j#JF|#D5kftpSF$(eHO#>rKWc68Ju{@fzd63&&$1J~nB; zX4lTE$$@OcMhCLkp{BTU>{GUx00ruik}jBR7wI>4GXh{vou()<-r5!@%`HF*FB za6IAR7~rf?%7Nscd9jp1t3kW$GAk+;Boju> zJn>UP9zF4yJwm)&{PK4hp@xl|&q z54Tk|p}}B)y}gX3LhocTWKq)Q#Eu;Zd}wnhag5h{jF)Ig17eBj++3n|+~?au>?){F zE?8S3zG}WL1^iWPJK}RqD}tF?U^~E6HEL-fTicf4pcdE`a8ixh+T0!2mSCF}+#0Y? zjoTYoCtD1yjGBNYb*VzIhoT{0YeJF4om}DS4I*4MuN)_Y-vuyxTS)d#{OpSScXhjx zGJYO1;AZx}-8KGy-91b8zl-x|A^I7p{G|nID9DKX7}ymB)HjJSR;I==mQW~!l=ec~CqElo&c!6Q_(obgB-^gx~sUNYlCJ!(`EZ)>t! ztW6>oYmLlJo~7|fZMc{E#w_u+EWCW2;nr>$izTDe`J%RDbh>18IuAS}HUhPpa#dFz zQhf*d@^+yykLt`-8-oos6+1;m5yh!QJU{PZky8>SPT^7DW%8@GkbbF6RM=*xX~~@n zE1u>&2E(h6)#u-CeyWhw=htRXG~6B=_TJ#!=_iikNsC!Hb@;0_?XhRhZYHuxG{LW< zo4e7#y61ww!>)NdH1>5^@^n}_be0aC-L^dT)S)Afh+?AlFj4Hkq6bdoXo*zhwtfpV zu+(Z@a*mT*kV7=?*2bN1F+`t ze`@@HJG++hzb?w72!x|If7K5t=3ZX}dkv72YcaR^n7e$;O+IpuUx;;`D!}qa3{=A)VyIXx)F`&KBr~vC?dYWFbK{r6AQz+~T!fL-k0c_(X3Vv(|ES2Y&r&Xks}E#T}) z%0BmTp~Y8#5dehrsbHiRN!g(tYzf*FR~659%Z3jLIaYXOqkwczn`VZtwNdZVX*4%C zO>aFW_OV;E9A-YmQ+5}059zjxb+gK%kb2l}No!hPj^4N6It4jOND-rijKQ0Tgz6Az z!1xyRtq?V}VVpj#VtF7tupFeLvSa0lTSP@*4O&_e){O$124-)XXMA^>PAPAF-9TU6Qq@xn#ZPy`6D|XNn%M(8p zB#LKN8+7g?kq`4$1rq=Gu4VYj6^_N2Wm88t0~2bbHEp9_VPR{&&*WzIDDmJ+qPcpxP2fGRkSd{ejh`30scSs1&7kx__ttT$R zvwE>)W1f%RvavQjJx%9X%e$mp0^3|>+0u&=IYJVUivYr_Pl)$jV3Hxro7lA~*p#0` zn(@>zGWH`>NDI3e^G{BiorRea7ps&s9 z?ld#aaj^$p4Gz!1)*kP{x+O}&jqB&)j#dAm-+fTx0KV0+rvw_>_Cuz^ijC@E<; z%?iM{f-rd;Qy3K~F z6%`nv61e%St3miaO0`*>Skv^7Ve2j!^6za9X6bo0&jR>=JX_Ko6Y{PtDE)6U{=c)m zJsSVBtG%;liT_`Wr*URmE(r>-aoytlGOnA{O<|PNigFZ@`mP|du z--NSRu}JtBZgZOkK{EzZj1~@QWla5t!8DMA9I}=RXa!L{T{N z$`%)4poy{9lwObU&(doGtR95btqPbHb`lC6N=hJ{MA#acS(25^cQk z0pI9|pC=>KgvY7RDl}nm=EDQjzd+WGX5F)<{%Hf&jbeJ2X7L|%7KMyMp$(0xLw)*C zmqIk45%rDr<7TnmC(qY?2xvLUf@2TY7Gft|{XEHa1vd*B%%$a2D=e$6tw_ycW&yh% zL|PBl1nu*f?ib=Qkrn*S#4Z=P5wKKrDptgCwIim(wUmV}F5>EW4A-%GK$tmlu;kFr zXo(6Sr&@rsHxngn)J`*9NKVY)LgwvZQicfh(dlo@{_kxDW$D?YPjmj?GhD0Wdu=)F z8-*0loR#(p^KYXG|KHWw6P5pUuIgH{|67zN`RcZ;<+OPPO-rKa6l+N|P8l>@!Cny9 zb8=`x$nw+f^WU%<>CNbJ%-ys`O0(+Xp=Bw}RCPl!hpRMP_rBBW_XmwIuS& zmJjAn+&IuH7a{YMFlve>|C=muTE3&>)35gmdvtQubS!!C=`hfsG$CS_4bD zlX8}gAsiqpOVR6e5p3cDV z?L(8*JgTzjjgJuerQ3y?#oMo2G7JA~A9ZzjU(2PV2G_pQ3 z*}rkBzi(=EWax}uWaYsA%_rP@ua$L$otH=#^TbVI=%_&&MT$g!pPC9$Z4#Ua5-plG zFgU(8v22B5qQtTlrUfcvlvviDXi1=Bk42>!vn8Qve6ZIhmhBMZp5j9@m(W6^Ld%4Q zDJA+hm(a9O=V;k*Z&QF6EokT-MI`h&!93%j%+B@}IEp7T!(&5zlbNaYgF~6M3D|Pj z6q_!^Mh9dnX}@GM>->StMF05U*yP~o$l63~vPf3$gcCFbTD_ee3ur85=qWk{jT(*2 z3@xrSxstVpjRHX@9ovZ#gUsNSo0%;SkIHgb@1a+%Yz@FbF{@0sjKOdd%zm+%;B1WL zqYe#wx}ou{Z(|leYevsr$_gH>WlhD_BqLPJd*=K>sfMoDEWNd>v z9n~t4HJr^=(hQ2_hvcFKd%}(vK8Qil97^UfPgO zm~OCv!ST7aWjjJkcaFBaw~xwy%4dQ6UvuIS(?%2iuf3~tb%g(0-O;|3|6@^}9XnFU z)tx*>%Pb!kQSVxmrhj-MKfIMgcpLkeE@EFdbzf%@UK0TYNQlzQ41Fv!Ord}jm)E0p zP=aSGRsi$Tb93PY$2)e2FFR3I_wcH26C1?DXeTh^kdhLZ#tUvJW}ygTy0oSBnMYer;L``tO6+% zG_g*qa@s|ucD;T|S*lWjHZfni$fHx&o4^pmrp%#uU4KAh60Fx&uRE-@Y1gA88%7}v zGMe74!4QYR%x{!KZSAIkj%9*_5!20Lzwg@hhr2;0{V0&SgI+(oesu6vbX2f)0(v$W ze-+aFMqg=e>F{5KXCCK2r=11e^;0ZhH=dv0w|E+#{~fD4I%?#<-Caxk|Drrev`NNb z2LT26m9aUWR)npZHd(+flgXG?P6pf-&TDn5F%R4s-2*Q?7SbJSQpl)CL4-{i8nbmD z+>b@Pr>=B+x~E$>>(=Cz5?Q6xR=E^<7uxAb^Pc92i(4s4tdcVHy6g$>^Ibt-BQ7Gg ziCrfDu9EWd3V7(6^@gq$S_ap|3U;kr6|I0A4h71swP<0%vu+AsMMO$6y93{?La627 z83n#f;UD zl+H-?wpbX`g6vHP^6*xKE7;*P9-f?(Gu<|wO39+rC}-gmruUtvj{mPY0lMosP!c8&wI;WEm z)J`K!n$+heLyJ=}4bh*)HtvmDFkDn=IJqDWk4%_pKz7gvkb|#r|Y@(Z9?db8Df>9K4 zL5xs50Wn@N%6PuZq1$RypapKnm>KbcDM7n7B|Cw>bH1h(X&q_QPfFF8jYoG8oZw=G z6p2SEm4O{!oK_+vf@G99e~M7-fXlH$mXCB#lu4=WrWs0*=}<5Ts;-X@3K6>ZCMRhf zRG^jdvV*46b?tMeS)QWln)lL%p+IIR)jXqbc!;*c6o?*IDzxr2j#dV1O`&_C4XP|A^~ zJz~=;f49}UfrGLXo>a=kWe@WOhf+CIy8`Lk6GH==Vxt6KPeSQ*nxjYmp({ksl1eb7 zEQ_ZX97QaVm1%O;uHgG6ueYtu)o0Rq%P*9(We>Zc!*(G1s!Yn+MtjcW23{N8*=?jm z(WU%t8!Tpuf#4uyQXHQ!{=p`OZnHJ7Zr3!LXih9(ITJS=SB5yKKxRPw4_u|?p>hcZ zgEIj$y5kFzoFMZUyB6ylA4v^cMVMr^MVn3HbP%?vq|-l$!f*#9mN6+KqmvoVpY+*& zft2$=C}0a2lHBp>RVXw=6-JNPW|(kjCrLis^RaHitw7;n0w%;H5R!*7C-eZMl~YCC z(ev08^vlz<(+k)UM0Wm6lX6spjRL>>Xq5l*;cqb52(_7&If>I~kaF(2!e{1#jch1M|jP9DPK)oT-k{82TvHP_bMAOm)kI(v1!&$b%m4wnJxQIJd34*OO z7R!gzd6PI;^9wFaX-Jj;LBQ;^ruCUY*rC=SZZ_i@>xo`AszioMO6Ga5*ULVk=dckR zt9-33hm#y64K;;4asQG;GTIX)Zi?LU26mS&a{dKti4Ie??(DaUD%*1dWf-EDZ9$Rr>fXC=IY%2Bo5ig&L+Xu@%r~)z4!_2=1G9N1s46Y)! ziNh$ZX&Y%zEVhgxp&`k^&gXn*JTu;_X*)-4Gkyqnj?}5P>%tl|&1V|!+tVm`F~WYU zMf_?BicDZ1O=G8$hBKpJ<$PcVrhT`Jr-8PIs;nIy%ZyBH99%y+)jzapVlp#64THd! zLrjHJH?7Nzk7On@6S77c4PkoNl^t%tC|5m%05h>qnYtB9Os|$S!yY?kiCFaf!;bIj zHtQt&JHx+CM~doZg|h7)UClcMtxn@`X_35JoQ{wk4a!H-PS-0hwOLA~a8l+-O`cUf zt{w3)zDDDgV(SK3-eTJeKG&<&xXn8CeLWxBoUi9=$~A5vsKIuO_+$}h82bgnW;Q4v z^I54J)vcx3;mGL+fT}5CgA2>3)6dS)CICh0O^}V%YYZ|d)CeT=32%s_S#|WHWu!5^ z@fmo&$jagkv8@3#oNRcPt{$qAa$_ z4B83NK|x|%$BAO)O1P|2?uIjD;2=`JO2B*1=$;JX%CYFxQrsUkGqQPVbKiJ}COtP3 z@NY*VTBI{tq%)z>+ce1R2c3qz8oezF@rC6f-3!9X3OPAuAvQRA^tvxlQ&3V~cPeO5 z6ojZWXEDJD6SL`A`lo0Eye+cl&b9rE9icxFin*-=#o^IFAj~Cku;ceaaTz2e36jwy8suSWLP?)^sq~3b z>v~e!s~8Dkvj)D5s$-LARq3!mAaICF%SK0wmb@sYgl{`qVL6s>>9$g(1+)wvJ@zaQ z1Vt;j9Hd1+Q_bj-NcFJaDSsmbm+Ezy4TB@7KQlf#xPGv|Z!!aKl~N~;WrkDOF^GxH zxW0()D_uV++DK+(pnelzuvZ7K@rgb(Ha@tyZ!&{U&7ARUa8ngou?WVr#nw~3b{=UJ&bh2z@C>zgIob3;?PsZlLZKG zMS1|0@|?20ERKj6#1b-5xddw7=sJ>8Cb^D6kR`@YU5M($3JW4th>_&%%!z!<1ig|_ zp~OjikJjC1X7*WaF*Ey5vAfLdb8=%v(AuRvwYQI{rDqR43+4aj&GacxGyk9V?r8p} zuCAs0e~a@_ri~N4(UJ9o8#ayifwS`FzM)N-2{e)Er$2%IC(&SFyJNW6q{pFdv$K!s zc_4{~FjDjj*yGA12lH?Y{1b67A~}E=va9QbS1B%ORU*Wv!4G_dICw2+0D9?#6kP5> zH7Dd+%w60A6yXr2U_6<{gaSt))a$la_Hc$DCTkN+)7o(Y`?vFibUK{~qrkM}B^RgU z5d}DBI#PnsgR&X&|Tgox;3}q%FPROdnwj7)mOFp!; zw>o5oxye+8MwazL>XW(gf@k?ILCUTt7rxFdNFi@lR?pgC`hY2W#p+nG zyA2hv3+tdZb3+oTX%tSB3RwjZ{mc&iAiY9tLGk&drKA6!`kDXv58G*1#6Qjae|kDP zYvR9lEXjWs=K=W-Ozq-{e~`*e)JV&f*4S~kp5DG$niK5fAZ48}8jUe~7Rz#425;hV zD&r(goRCjTk<>IR&908BpbG9u;UJg%Wf0qvzmOp<`R`C9%Q_;j8bk)x#iKH?Zg(RS zBaRaS4JOl|XA{^`w5qE?$Q+m!*yIW2=(QZ1X%1(E_}l_M2o|O;C{RF1!3B%f!@>ax zse}~R2#|x!gbi7KkStEZ7VRU?GI1(fP0@cDuObgR(f$gN$DAuQ*FqOt(!mf|zA^xm zk7`8@VXiBIsK*haA9kd}s4%lhr^*$M3}iUPwixN~_L8YC{ep{e(0Q*{h{#$+3|%(f zS%L045zR;rfwD#GZcRDdK}#GSHvrZhI=}%;HxSD5_SGH;)GUurV!1>aI?DcYux{B= z5#weu5~1{N5(qSwjyt0T4KLi5_UcWd%*39TT2#mlRi^OlOoB`73o;m zl9XE|$X0#A289j*aX=iSTMk5j^`zOIxFt!TIut-2j}HqRAO%&_w_*ed|HAu;wUNch zGYZ%&+l<2A#r_1M zJdH}a4!9#hQ8jk1 zR{Hpf?EwC%Lz3|+v;fn(_YBejk3fq1ZLc27v+g=)8mmIF+PE_phQgYPY^l987hnv zg7V3!O8;w;LtEDpA+Ea7E2BE=J3=r&%5Fch_@1h!--g#pz2`-nYA*Wo-%FMZN zn2Q_)QfLQCH+r4)%O&P~r5k=(w?*9|q`%K%RIu^|IeJM%Tx63O$}{EE`~`H42*!E^ zz3hOgl++nE=_N&%Vr~R-)3=1x#7HUE|Jhf zSs^;3jq0;|rcpK7M2|9~+$v5O@ks}GuMtlxzy^W+gO%^%ZDs8F;eAxZMMAHUiH@H3 z_F*fbeltpC`k}qOy{Npmt)f*ANY{oq2%Q{4L-xK#LC-YwOC0uY;jkB-ciaQaQRu=v zunz9$;MANdkRo^t5u{g$Wzt4)vE*A>n;)i&bZQzlDVym$A$c2vOJsg4PASMVIE6-t zKj_qaXA-VBb~eSMY%ej7OU&aE^Y~n29);O_zz8YFT%Sn{zX%F*o z;dDj`j}&o=ze^ePCB&afEUAnCv7QC$e|N?FtBL-%yR)MsYX9HW(cQhI|6PnHInQW@ zsrr8H{SY5AiN-dq8yf77i@n7Y^;jMc(jr32Fq__}c@C$HF1B%n-txqesaQcvm2({O z66d-Y2bwMs<%Zk$aLhC~VkA$YM7M&|P3?;Au&_V{QnpRF5z0JBI?qvv3}RATSwsWC zpXF4J)RgVPWfJQ~Arh;GjpH!!WDqevR6@GKBKWu>HlA+FV3S-I$J!ElEx6r6>@u)w zCl2L)tz5`HOd0e@2r|Zl2IgNdPqZoe?@U4WAu>9mE+a7_n$>F6~u}-tO)$)?yzduB3#@ z1#?Ozh;2CEl&7X!S}~RxM%>MzB^@&;2q}>I`^19Zqs;@vsI7zBnk6I`Um1DVjR!4jh>u{A}MZFgFj<)+a(83d`dUJPO_8FOyS z;IdImUnNvpq)m$-K9S`pQ{V{zmIsOqy9yp9mW?4;Q`wiMA7Id9f*>#OMG7oxo%_$d z+z+~M(GGCfOavL&(a>QM_FuWOPidu$LsZnAGEicEa!s)CJSM>&YXKl&hm`XLElDp) z+^yb&P-0pVotXhGOI(m6x&@-N_UsiR23i5zrL^FnLC|Ls!)uc^ax#-#8`I;YWD8=r zy|xxD39UqfBGTawOsBvFDuh*RSS}vbh%02YWTPkxQl}CdDJkBD8>obb#Ys^1*vMzu zxg-*esdm)t^b7VtA3CrcRMF_9~;E7wq znu#c)XY>sZNv|nkqR+Y37!zwP$tCFyi3?>)$6uJ0Q|2oiX>uksYB}Aq)AU3mt_hk8 z23s6U7LPnfi&;*-l^uNi6a%w2JX^9Y!}5a};5KR?Z;&1n%0vftHZFITLwZHGY*_v= z-4WS5MWilRiY`WC-HB1OtE~*UjI75FVtz7<&{Ry!^KYGI@$B z3lif(-?=7df`W={I)&)NWT6{bTsAfl>;UIsPkCDFAo(PNt+O?oGBL=@uqjavH|4QF zv^@JKonpFGuIG7g?`g7Fwn3{VL}v_l3sM?*(j%@&!Gge6u0#=D zt&YP+;PM!WdC!0co+EI+*8@UwK6Zk8S;F&m$JAXj5w|EHP8pkRd3OO)9|Y=)P!O*b z6)TqR?D$y^rBz7vj43kMpNSWiU5*~wLJX*reM8V4W@}%T(#5lLhHzr5}DH&&R z#4O@4&{^GMH@;ve_KgiHk>I&^3LA+ut27aCzAoEm3TP-EV8vzstxP9BV|iFG&H(}8 zV8@8(fwqh*oPcj>6^6ge2B51Ib<@%^Fq>-A++d^zJ>McJF>mu6A~`yIpDtjCn)ij4 zqnn4QOnS(PR@w{m{SszN=>e<50tqtVGaxah?ff(m>!~2=nu(NPR5>?zIZe2_+#wom;dVZqy5o+!8z^R7OEID}@c>qQ@Xgi+RPiyjV>`t&|M* zW|78j_R}oD8fz<+lJtQwXRWAD#5O`axKS(Wm%)ahbqavXuER#|k}$xMVUr4Rg~Rda zrdeHP3lE`UxdevGCWi9?tl%pAF7=wM;KV-RzXuLTMcCI0cp=1(^S!?PV zk|iVa9WzJGaZieCN@PFto}{&;NFm2Ns>nB0FTG%-89eBdWLq1JoK#KLI^ZZlPB}}! ziE30oS)-hcC=o*nNB%pakd!sn)YRxs2wW$k+EYseq2Q|}<&#vscoSjL1O2E82BFe# zB#g4vQ*9Hd@>H`Oel?^pX%Y1kgP|OMy_6L-%ly!%pZAKfd#$B=BQy6}!}M4K_XgJO z^MC*!_OxA6)G8_7Ch6H(B(d%C95O}Pbz`LF=15BhNlOMvO9n~*U%+D$g_2?!0%V%x{K{9C)c%Ja#$(_cnnl2Ck^WWq8EYs z98qoVQE}x|<8JW*^3aTstEkz5Lh&m=s_ghWzcGg;Ck?gXps<;ixR2wCg=eNEKg3j5 zOt1~YJWt+W6|gK2CtLfGIL;A~-EQt+SZ9FZ)CTkEU>PDU2OVtIHy)XJ&-QIMO&;%? z0*7^zfw!%#7~xrLu&gn}rGRI2m#uu>u>nQQCBo1XMOxIV#Iu)@nb3e`D$MOSa2Br1 zh|0YY5M5$=ON{CNdB(KKxeu~-U=d)F=f_llutIoN@Pj4n<1r z!-h|~Vc?RF%`}+%6w97$M^M4(np6_Hr)F>g;h;~@3~{%n#n}{2;}BvNxWI4sjgb^# z4(1{w5gCYujYHVIEE$Z0Onfo_afo9GStJ;imZD~W26I9;){3&A0T+6%8dlq82Y_NP zfC86GmY$*pyy^n!Tg*(%!v=9oudZQA%v^BU_>6A(ba#ovJt-!M<+K*~y5UJk0~f^9 zUmo_wd&Ki#c+BR2p2=(^xWp7J-YqAu&bnVvztY>Qhiu~HnX;Q}l|&{mXkY=o6z#AT z;&H74;F?CGuzLACGo#iLkHRlR_o~mXVu$Gyv>m%d`kl7Qc3g}+-?D8Uj?P53?lZUI zpq~|s*vulR1l8&IMD_z8N9kBR59xEw+S+Y`=-Lb7uF9l4LXNFW#@r*FVCu=Gdtz%z zKURvra03rKW!Oyf_aabWltri8uS87Vi-QOYVni0v4 zP!X~nNe!n^1cA3WSBO$}qJMNeGqrAPeeh;vbgF-JXh@jsN_CCQpwz2W(n1;`ItFy5 z($SCJJirKz-^p4-R}vuaeDlB!llO|7w+L0Be9vTE!20uB3L=o_9Fi>u?!XiS-Yn34 zh$5vl%)tk(x7KTG2JC88zhj@oGzCmXe5Rhr1-$9r4lB%d$DR(>)2{C2uFhTA%N;d3 zrqw-xNBZ6gKok>xD5Y@m3C6~A9D{^BgS%xK1hmLJ#N_>%2X(EPkdCGk(pfVh9f^4& zKSC#D(5YYtGM|P!074Ib-0$Ho#GMZvyH|4=-hc~KUMe_seiII|^ltPKqVHuuk-UWmvB=thwfzJXOb%0Q^SRvBLuv)?%r?-}0V=cxA zqYS+l1SVu=6)yJ5whu;u4#KX>2aS`$;7n49ps>uhwzDNB28@ND3Q~5U5&OES`#M@7O#LChw9K>A0&qcWM|;mirOXV?@tH>eP#r6rJ6HG645rMTr&`LF zh$(V80a*IGCa06!9d)uhfy)kYw?aDkpxZSbKLrcBx@#2Z)u&b1C3)EKxS6u-Is9U_ zewM>rV|12^pTY*eFUw%zqR|Sl0*;PHi?~rM_9EG8&_W2Zqq{Dd0m)4=3>6H~BSsBM z;t1MTB>`6w_~^{6@9IHI5yTkTwnM^(Vl}0N=a9cD%;y3jbw-pr!CP5TdBtmokfO6& z4>7cY)YwsmXSNktX`F6V2EgOtgi6F5iuR~P%t)_-H$l%pvJ}@jS~#YIk=JpZtiMKS zZ{=EMroYjNkr~t&BEx4)@qB4hBYne}UiAfdghkp84X)}=pg12o++Gq%8=XK##T{yx z*hv|e;B7F}p?7_;g+*_;mrf%@13uBzagi|NumIPnq0`<*w^m~j;94W9dye27@I|44 z6)&FySO&+b*c3p>x8kZa<`2%YqF&-emIKrsksT0>BKgG?1U3oIcC?9bt(2f-b({9v zO|(Kt2F3c2U4b}QL7ym>!J{G3Lq0%Ag}*YvQ0A_!Wyi$aNN_8z3OrrR%{VJK=zkCx zYej5wLpk29kzsBXquV0jE9u`^fd5v+)9?d{Wo^5jkNg>;q!CpdmL1}x1lw$C|gzOapJHSG^(pqrUR`OF2E)v!qfSV9D2MNxj(z7v(F>NAjTv` z%pFU)7aK)3KwU+axOoLx#Jjx`oKDrlRqb7uI*qMJ{{* zlwK)Ape5<{lt%B&zF1fNKADe`Wn=DR!}a=LQ^2BzGd8fyVn`#)fn7vvsIDk8QHM0{ zE^2~TT6#S#p5B0cwq}5sgQc~LDS;7EVG32`MpkI82+S5@heaquek0)2C$!T5{~2Kg zZaGZTCXKxrXyF^zH#Vp`Fz6*~0)F+XqIcz%AuOnrC^sN44Zz3&SCiO9{7<;LmewqB zu{D=BakUE6@HvBBWxAL>J&>;Z-YG>kpWSzx-adtSN7+GqZ9b%t30S68bAyv;df zC-4blns9bpWr2+imV*Kl&QmDmVX0Q53wb)Od(%Q`M7tC2H*+&9%3RERCo+du52O)! zq2#3K1^0BZ8c;2OYmb z97p(CiXrn!;AO)4&^JCZII^Kvq!N=D3GkGw3)ok{Qy7(4emIAQ>k9^mdC7}Ll~fwM z>T)mS)0*a-D9AD3vQp+r;H2-c(gDze=O84tA$;U`PL6sBdpvd8c5}9#x-MS4QQ_bv z1dh_%hm$Lim**1~G1i^1C&OXX2L^zc!N@X{*4; zpM#g2LU2s?OUZ5!@`C|e?(r$)9hNLoG^REOPWOJDpw{XdR}-fU&L>`ZD~Hd0ze6sn zB9(7#yA0LZ80Yo!x_B|@Ei|u7Y*v@L5vObBbm5_=7ZP}SAyKDeVot|JoZb!brg^k! z$wV+@pL+_`2H9L<60pQ)a%q&uWj;U_xSR&o?co(Qun9C|~PFAR``6F~Gy>2tlr4-#|`+sPr3tPim{ANFL% zhuC}%dotTYY_5m-WO}GKdo_WhYr{s@P4Ezt-60w@I@YbbPEv{(k@f0RR6t6AY~YfCc~}+5IyB literal 0 HcmV?d00001 diff --git a/rhacs/4.5.2/central-services/.helmignore b/rhacs/4.5.2/central-services/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/Chart.yaml b/rhacs/4.5.2/central-services/Chart.yaml new file mode 100644 index 0000000..131928e --- /dev/null +++ b/rhacs/4.5.2/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.5.2 +appVersion: 4.5.2 diff --git a/rhacs/4.5.2/central-services/README.md b/rhacs/4.5.2/central-services/README.md new file mode 100644 index 0000000..e653870 --- /dev/null +++ b/rhacs/4.5.2/central-services/README.md @@ -0,0 +1,221 @@ +# 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 + + scannerV4: + # Enable Scanner V4, which will become the default scanner for StackRox. + # Note that enabling Scanner V4 while having the StackRox Scanner disabled (scanner.disable=true) + # is not a supported configuration. + disable: false + + 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. + +Alternatively, you can also use the `--reuse-values` for the `helm upgrade` command. This flag +causes values which were previously passed via `--values / -f`, `--set` or `--set-file` to be +automatically passed again to the Helm chart rendering. + +### Passing Generated Values + +The Helm chart can conveniently automatically generate certain sensitive data objects. This includes +passwords, keys and certificates. If these data objects were generated during the installation +of the Helm chart, a command is provided as part of the post-installation notes which can be used +for retrieving them and storing them in a file `generated-values.yaml`. This file +might contain a CA key. + +If, during an upgrade of the Helm release, the Helm chart needs to generate a new certificate for +some component, it is required to pass in the existing CA, for example by adding +`-f generated-values.yaml` to the arguments for `helm upgrade`. + +### Enabling Scanner V4 + +Beginning with StackRox 4.4, a new scanner component based on ClairCore named Scanner V4 is integrated. +In a future version of StackRox, Scanner V4 will become the new default scanner and replace the existing +scanner named StackRox Scanner. Currently, Scanner V4 is not installed by default, but it +can be enabled alongside StackRox Scanner using the following Helm chart setting: + +``` +scannerV4: + disable: false +``` + +To enable Scanner V4 for an existing installation of this chart, the CA certificate +and its key must be provided to the `helm upgrade` command. +For example, if the CA was generated ahead of time and injected into the `helm install` command, then +the `--reuse-values` flag for `helm upgrade` can be used to provide the certificate and key. However, if the CA was +generated by the Helm chart at installation time, you must retrieve the generated secret +values from the cluster (see above) and provide those to the `helm upgrade` command. + +Note that because Scanner V4 currently runs simultaneously with StackRox Scanner, your +cluster must have sufficient computing resources available to host both scanner components at the same time. +The default resource configuration for Scanner V4 components can be found in the file +internal/defaults.yaml. diff --git a/rhacs/4.5.2/central-services/assets/Red_Hat-Hat_icon.png b/rhacs/4.5.2/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/rhacs/4.5.2/central-services/assets/StackRox_icon.png b/rhacs/4.5.2/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/rhacs/4.5.2/central-services/config-templates/scanner-v4-db/pg_hba.conf.default b/rhacs/4.5.2/central-services/config-templates/scanner-v4-db/pg_hba.conf.default new file mode 100644 index 0000000..650f2fe --- /dev/null +++ b/rhacs/4.5.2/central-services/config-templates/scanner-v4-db/pg_hba.conf.default @@ -0,0 +1,23 @@ +# 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 reject +host replication all 127.0.0.1/32 reject +host replication all ::1/128 reject + +### 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.5.2/central-services/config-templates/scanner-v4-db/postgresql.conf.default b/rhacs/4.5.2/central-services/config-templates/scanner-v4-db/postgresql.conf.default new file mode 100644 index 0000000..63ed892 --- /dev/null +++ b/rhacs/4.5.2/central-services/config-templates/scanner-v4-db/postgresql.conf.default @@ -0,0 +1,75 @@ +#------------------------------------------------------------------------------ +# FILE LOCATIONS +#------------------------------------------------------------------------------ + +hba_file = '/etc/stackrox.d/config/pg_hba.conf' + +#------------------------------------------------------------------------------ +# CONNECTIONS AND AUTHENTICATION +#------------------------------------------------------------------------------ + +# - Connection Settings - + +listen_addresses = '*' +max_connections = 500 + +# - Authentication - + +password_encryption = 'scram-sha-256' + +# - SSL - + +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' + +#------------------------------------------------------------------------------ +# RESOURCE USAGE (except WAL) +#------------------------------------------------------------------------------ + +# - Memory - + +# Keep this in sync with the shared-memory volume in the +# templates/02-scanner-v4-07-db-deployment.yaml +shared_buffers = 750MB +work_mem = 16MB +maintenance_work_mem = 128MB +dynamic_shared_memory_type = posix + +#------------------------------------------------------------------------------ +# WRITE-AHEAD LOG +#------------------------------------------------------------------------------ + +# - Checkpoints - + +max_wal_size = 3GB +min_wal_size = 80MB + +#------------------------------------------------------------------------------ +# REPORTING AND LOGGING +#------------------------------------------------------------------------------ + +# - What to Log - + +log_timezone = 'Etc/UTC' + +#------------------------------------------------------------------------------ +# CLIENT CONNECTION DEFAULTS +#------------------------------------------------------------------------------ + +# - Locale and Formatting - + +datestyle = 'iso, mdy' +timezone = 'Etc/UTC' + +lc_messages = 'en_US.utf8' +lc_monetary = 'en_US.utf8' +lc_numeric = 'en_US.utf8' +lc_time = 'en_US.utf8' + +default_text_search_config = 'pg_catalog.english' + +# - Shared Library Preloading - + +shared_preload_libraries = 'pg_stat_statements' diff --git a/rhacs/4.5.2/central-services/config-templates/scanner-v4/indexer-config.yaml.tpl b/rhacs/4.5.2/central-services/config-templates/scanner-v4/indexer-config.yaml.tpl new file mode 100644 index 0000000..c5d28fc --- /dev/null +++ b/rhacs/4.5.2/central-services/config-templates/scanner-v4/indexer-config.yaml.tpl @@ -0,0 +1,47 @@ +{{- /* + This is the configuration file template for the Scanner v4 Indexer. + 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 v4 Indexer. +stackrox_services: true +indexer: + enable: true + database: + conn_string: > + host=scanner-v4-db.{{ .Release.Namespace }}.svc + port=5432 + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + user=postgres + sslmode=verify-full +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.statementTimeoutMs) }} + statement_timeout={{._rox.scannerV4.db.source.statementTimeoutMs}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.minConns) }} + pool_min_conns={{._rox.scannerV4.db.source.minConns}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.maxConns) }} + pool_max_conns={{._rox.scannerV4.db.source.maxConns}} +{{- end }} + client_encoding=UTF8 + password_file: /run/secrets/stackrox.io/secrets/password + get_layer_timeout: 1m + {{- if ._rox.env.centralServices }} + repository_to_cpe_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?file=repo2cpe + name_to_repos_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?file=name2repos + {{- else }} + repository_to_cpe_url: https://sensor.{{ .Release.Namespace }}.svc/scanner/definitions?file=repo2cpe + name_to_repos_url: https://sensor.{{ .Release.Namespace }}.svc/scanner/definitions?file=name2repos + {{- end }} + repository_to_cpe_file: /run/mappings/repository-to-cpe.json + name_to_repos_file: /run/mappings/container-name-repos-map.json +matcher: + enable: false +log_level: "{{ ._rox.scannerV4.indexer.logLevel }}" +grpc_listen_addr: 0.0.0.0:8443 +http_listen_addr: 0.0.0.0:9443 +proxy: + config_dir: /run/secrets/stackrox.io/proxy-config + config_file: config.yaml diff --git a/rhacs/4.5.2/central-services/config-templates/scanner-v4/matcher-config.yaml.tpl b/rhacs/4.5.2/central-services/config-templates/scanner-v4/matcher-config.yaml.tpl new file mode 100644 index 0000000..4414553 --- /dev/null +++ b/rhacs/4.5.2/central-services/config-templates/scanner-v4/matcher-config.yaml.tpl @@ -0,0 +1,39 @@ +{{- /* + This is the configuration file template for the Scanner v4 Matcher. + 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 v4 Matcher. +stackrox_services: true +indexer: + enable: false +matcher: + enable: true + database: + conn_string: > + host=scanner-v4-db.{{ .Release.Namespace }}.svc + port=5432 + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + user=postgres + sslmode=verify-full +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.statementTimeoutMs) }} + statement_timeout={{._rox.scannerV4.db.source.statementTimeoutMs}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.minConns) }} + pool_min_conns={{._rox.scannerV4.db.source.minConns}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.maxConns) }} + pool_max_conns={{._rox.scannerV4.db.source.maxConns}} +{{- end }} + client_encoding=UTF8 + password_file: /run/secrets/stackrox.io/secrets/password + vulnerabilities_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?version=ROX_VERSION + indexer_addr: scanner-v4-indexer.{{ .Release.Namespace }}.svc:8443 +log_level: "{{ ._rox.scannerV4.matcher.logLevel }}" +grpc_listen_addr: 0.0.0.0:8443 +http_listen_addr: 0.0.0.0:9443 +proxy: + config_dir: /run/secrets/stackrox.io/proxy-config + config_file: config.yaml diff --git a/rhacs/4.5.2/central-services/config-templates/scanner/config.yaml.tpl b/rhacs/4.5.2/central-services/config-templates/scanner/config.yaml.tpl new file mode 100644 index 0000000..5efc0b9 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/config/central/config.yaml.default b/rhacs/4.5.2/central-services/config/central/config.yaml.default new file mode 100644 index 0000000..d85c852 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/config/central/endpoints.yaml.default b/rhacs/4.5.2/central-services/config/central/endpoints.yaml.default new file mode 100644 index 0000000..25549d6 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/config/centraldb/pg_hba.conf.default b/rhacs/4.5.2/central-services/config/centraldb/pg_hba.conf.default new file mode 100644 index 0000000..8229f95 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/config/centraldb/postgresql.conf.default b/rhacs/4.5.2/central-services/config/centraldb/postgresql.conf.default new file mode 100644 index 0000000..057e7ea --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/config/proxy-config.yaml.default b/rhacs/4.5.2/central-services/config/proxy-config.yaml.default new file mode 100644 index 0000000..73df050 --- /dev/null +++ b/rhacs/4.5.2/central-services/config/proxy-config.yaml.default @@ -0,0 +1,27 @@ +# # NOTE: Central, Scanner, Scanner v4 Indexer, and Scanner v4 Matcher 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 +# # - $KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT +# 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.5.2/central-services/internal/annotations/helm-hook_secret.yaml b/rhacs/4.5.2/central-services/internal/annotations/helm-hook_secret.yaml new file mode 100644 index 0000000..68eea0c --- /dev/null +++ b/rhacs/4.5.2/central-services/internal/annotations/helm-hook_secret.yaml @@ -0,0 +1,2 @@ +helm.sh/hook: pre-install,pre-upgrade +helm.sh/resource-policy: keep diff --git a/rhacs/4.5.2/central-services/internal/annotations/helm-hook_storage.yaml b/rhacs/4.5.2/central-services/internal/annotations/helm-hook_storage.yaml new file mode 100644 index 0000000..7376533 --- /dev/null +++ b/rhacs/4.5.2/central-services/internal/annotations/helm-hook_storage.yaml @@ -0,0 +1,3 @@ +helm.sh/hook: pre-install,pre-upgrade +helm.sh/resource-policy: keep +helm.sh/hook-delete-policy: never diff --git a/rhacs/4.5.2/central-services/internal/bootstrap-defaults.yaml.tpl b/rhacs/4.5.2/central-services/internal/bootstrap-defaults.yaml.tpl new file mode 100644 index 0000000..8f8e559 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/internal/config-shape.yaml b/rhacs/4.5.2/central-services/internal/config-shape.yaml new file mode 100644 index 0000000..96a2d8a --- /dev/null +++ b/rhacs/4.5.2/central-services/internal/config-shape.yaml @@ -0,0 +1,192 @@ +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 + storageClasses: + all: {} # dict + default: null # string + pvcs: + names: null # [string] +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] + hostAliases: null # [dict] + affinity: null # dict + priorityClassName: null # string + 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] + hostAliases: null # [dict] + priorityClassName: null # string + 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 + scanner-v4-indexer: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner-v4-matcher: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner-v4-db: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + other: {} # dict +allowNonstandardNamespace: null # bool +allowNonstandardReleaseName: null # bool +allowUnsupportedHelmVersion: 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 +network: + enableNetworkPolicies: null # bool +system: + enablePodSecurityPolicies: null # bool diff --git a/rhacs/4.5.2/central-services/internal/defaults.yaml b/rhacs/4.5.2/central-services/internal/defaults.yaml new file mode 100644 index 0000000..3463978 --- /dev/null +++ b/rhacs/4.5.2/central-services/internal/defaults.yaml @@ -0,0 +1,331 @@ +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.5.2 + + 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.5.2 + + 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.5.2 + + dbResources: + limits: + cpu: "2000m" + memory: "4Gi" + requests: + cpu: "200m" + memory: "512Mi" + + dbImage: + name: rhacs-scanner-db-rhel8 + tag: 4.5.2 + scannerV4: + disable: true + image: + name: rhacs-scanner-v4-rhel8 + tag: 4.5.2 + indexer: + disable: false + logLevel: INFO + metricsPort: 9090 + replicas: 3 + autoscaling: + minReplicas: 2 + maxReplicas: 5 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: + app: scanner-v4-indexer + 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: "3Gi" + cpu: "2000m" + matcher: + logLevel: INFO + metricsPort: 9090 + replicas: 2 + autoscaling: + minReplicas: 2 + maxReplicas: 3 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: + app: scanner-v4-matcher + 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: "500Mi" + cpu: "1000m" + limits: + memory: "2Gi" + cpu: "2000m" + db: + postgresConfig: "@config-templates/scanner-v4-db/postgresql.conf|config-templates/scanner-v4-db/postgresql.conf.default" + hbaConfig: "@config-templates/scanner-v4-db/pg_hba.conf|config-templates/scanner-v4-db/pg_hba.conf.default" + source: + minConns: 5 + maxConns: 40 + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Scanner V4 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 + resources: + requests: + cpu: "200m" + memory: "3Gi" + limits: + cpu: "2000m" + memory: "4Gi" + image: + name: rhacs-scanner-v4-db-rhel8 + tag: 4.5.2 + exposeMonitoring: false + + network: + enableNetworkPolicies: true + + system: + +pvcDefaults: + claimName: "stackrox-db" + size: "100Gi" + +dbPVCDefaults: + claimName: "central-db" + size: "100Gi" +scannerV4DBPVCDefaults: + claimName: "scanner-v4-db" + size: "50Gi" + createClaim: true diff --git a/rhacs/4.5.2/central-services/internal/expandables.yaml b/rhacs/4.5.2/central-services/internal/expandables.yaml new file mode 100644 index 0000000..5054a52 --- /dev/null +++ b/rhacs/4.5.2/central-services/internal/expandables.yaml @@ -0,0 +1,71 @@ +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 +scannerV4: + indexer: + nodeSelector: true + resources: true + serviceTLS: + cert: true + key: true + matcher: + nodeSelector: true + resources: true + serviceTLS: + cert: true + key: true + db: + nodeSelector: true + resources: true + postgresConfig: true + hbaConfig: true + password: + value: true + serviceTLS: + cert: true + key: true diff --git a/rhacs/4.5.2/central-services/internal/platforms/default.yaml b/rhacs/4.5.2/central-services/internal/platforms/default.yaml new file mode 100644 index 0000000..180f5c8 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/internal/platforms/gke.yaml b/rhacs/4.5.2/central-services/internal/platforms/gke.yaml new file mode 100644 index 0000000..70d7b32 --- /dev/null +++ b/rhacs/4.5.2/central-services/internal/platforms/gke.yaml @@ -0,0 +1,2 @@ +pvcDefaults: + storageClass: "stackrox-gke-ssd" diff --git a/rhacs/4.5.2/central-services/internal/scanner-config-shape.yaml b/rhacs/4.5.2/central-services/internal/scanner-config-shape.yaml new file mode 100644 index 0000000..1a5d26f --- /dev/null +++ b/rhacs/4.5.2/central-services/internal/scanner-config-shape.yaml @@ -0,0 +1,44 @@ +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] + hostAliases: null # [dict] + dbHostAliases: null # [dict] + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + affinity: null # dict + priorityClassName: null # string + dbPriorityClassName: null # string + 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.5.2/central-services/internal/scanner-v4-config-shape.yaml b/rhacs/4.5.2/central-services/internal/scanner-v4-config-shape.yaml new file mode 100644 index 0000000..a705b53 --- /dev/null +++ b/rhacs/4.5.2/central-services/internal/scanner-v4-config-shape.yaml @@ -0,0 +1,79 @@ +scannerV4: + disable: null # bool + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + indexer: + disable: null # bool + metricsPort: null # int + logLevel: null # string + replicas: null # int + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + matcher: + metricsPort: null # int + logLevel: null # string + replicas: null # int + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + db: + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + source: + minConns: null # int + maxConns: null # int + statementTimeoutMs: null # int + configOverride: null # string + password: + value: null # string + generate: null # bool + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + postgresConfig: null # string + hbaConfig: null # string + 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] + exposeMonitoring: null # bool diff --git a/rhacs/4.5.2/central-services/templates/00-additional-ca.yaml b/rhacs/4.5.2/central-services/templates/00-additional-ca.yaml new file mode 100644 index 0000000..67b0c2b --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/00-image-pull-secret.yaml b/rhacs/4.5.2/central-services/templates/00-image-pull-secret.yaml new file mode 100644 index 0000000..1fc3e34 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/00-injected-ca-bundle.yaml b/rhacs/4.5.2/central-services/templates/00-injected-ca-bundle.yaml new file mode 100644 index 0000000..3289c2a --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/00-proxy-config-secret.yaml b/rhacs/4.5.2/central-services/templates/00-proxy-config-secret.yaml new file mode 100644 index 0000000..c357179 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/00-stackrox-application.yaml b/rhacs/4.5.2/central-services/templates/00-stackrox-application.yaml new file mode 100644 index 0000000..5d320f8 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/00-stackrox-application.yaml @@ -0,0 +1,124 @@ +{{- 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 +{{- if ._rox.network.enableNetworkPolicies }} + - group: networking.k8s.io + kind: NetworkPolicy +{{- end }} + - 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.5.2/central-services/templates/00-storage-class.yaml b/rhacs/4.5.2/central-services/templates/00-storage-class.yaml new file mode 100644 index 0000000..ed5c3a0 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/00-storage-class.yaml @@ -0,0 +1,26 @@ +{{- include "srox.init" . -}} + + +{{- $name := "stackrox-gke-ssd" -}} +{{- if has $name ._rox._state.referencedStorageClasses }} + {{- $lookupOut := dict -}} + {{- $globalName := include "srox.globalResourceName" (list . $name) -}} + {{- $_ := include "srox.safeLookup" (list . $lookupOut "storage.k8s.io/v1" "StorageClass" "" $globalName) -}} + {{- if and (not $lookupOut.result) (or .Release.IsInstall $lookupOut.reliable) (not ._rox.meta.noCreateStorageClass) }} + +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ $globalName }} + labels: + {{- include "srox.labels" (list . "storageclass" $name) | nindent 4 }} + annotations: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "storageclass" $name $annotations) | nindent 4 }} +provisioner: kubernetes.io/gce-pd +parameters: + type: pd-ssd + + {{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/01-central-00-db-serviceaccount.yaml b/rhacs/4.5.2/central-services/templates/01-central-00-db-serviceaccount.yaml new file mode 100644 index 0000000..e48883a --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-00-serviceaccount.yaml b/rhacs/4.5.2/central-services/templates/01-central-00-serviceaccount.yaml new file mode 100644 index 0000000..8c257f6 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-01-license-secret.yaml b/rhacs/4.5.2/central-services/templates/01-central-01-license-secret.yaml new file mode 100644 index 0000000..0d26dda --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-02-db-psps.yaml b/rhacs/4.5.2/central-services/templates/01-central-02-db-psps.yaml new file mode 100644 index 0000000..870dd40 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-02-db-psps.yaml @@ -0,0 +1,80 @@ +{{- 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.db.persistence.hostPath }} + allowedHostPaths: + - pathPrefix: {{._rox.central.db.persistence.hostPath}} + {{- 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.5.2/central-services/templates/01-central-02-db-security.yaml b/rhacs/4.5.2/central-services/templates/01-central-02-db-security.yaml new file mode 100644 index 0000000..6017d09 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-02-db-security.yaml @@ -0,0 +1,44 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.env.openshift }} +--- +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: + - nonroot-v2 + {{- if ._rox.central.db.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.5.2/central-services/templates/01-central-02-psps.yaml b/rhacs/4.5.2/central-services/templates/01-central-02-psps.yaml new file mode 100644 index 0000000..1ba51f5 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-02-security.yaml b/rhacs/4.5.2/central-services/templates/01-central-02-security.yaml new file mode 100644 index 0000000..4976d63 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-02-security.yaml @@ -0,0 +1,44 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.env.openshift }} +--- +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: + - nonroot-v2 + {{- 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.5.2/central-services/templates/01-central-03-cloud-credentials-rbac.yaml b/rhacs/4.5.2/central-services/templates/01-central-03-cloud-credentials-rbac.yaml new file mode 100644 index 0000000..e9bb421 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-03-cloud-credentials-rbac.yaml @@ -0,0 +1,34 @@ +{{- include "srox.init" . -}} + +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: central-sts-config-reader + namespace: {{ .Release.Namespace }} + annotations: + {{- include "srox.annotations" (list . "role" "central-sts-config-reader") | nindent 4 }} + labels: + {{- include "srox.labels" (list . "role" "central-sts-config-reader") | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["secrets"] + resourceNames: ["gcp-cloud-credentials"] + verbs: ["get", "list", "watch"] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: central-sts-config-reader + namespace: {{ .Release.Namespace }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "central-sts-config-reader") | nindent 4 }} + labels: + {{- include "srox.labels" (list . "rolebinding" "central-sts-config-reader") | nindent 4 }} +subjects: + - kind: ServiceAccount + name: central + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: central-sts-config-reader + apiGroup: rbac.authorization.k8s.io diff --git a/rhacs/4.5.2/central-services/templates/01-central-03-diagnostics-rbac.yaml b/rhacs/4.5.2/central-services/templates/01-central-03-diagnostics-rbac.yaml new file mode 100644 index 0000000..4c83007 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-04-htpasswd-secret.yaml b/rhacs/4.5.2/central-services/templates/01-central-04-htpasswd-secret.yaml new file mode 100644 index 0000000..59b338e --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-05-db-tls-secret.yaml b/rhacs/4.5.2/central-services/templates/01-central-05-db-tls-secret.yaml new file mode 100644 index 0000000..3a3a1fa --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-05-tls-secret.yaml b/rhacs/4.5.2/central-services/templates/01-central-05-tls-secret.yaml new file mode 100644 index 0000000..1850d46 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-06-default-tls-cert-secret.yaml b/rhacs/4.5.2/central-services/templates/01-central-06-default-tls-cert-secret.yaml new file mode 100644 index 0000000..010444c --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-08-configmap.yaml b/rhacs/4.5.2/central-services/templates/01-central-08-configmap.yaml new file mode 100644 index 0000000..9420e59 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-08-db-configmap.yaml b/rhacs/4.5.2/central-services/templates/01-central-08-db-configmap.yaml new file mode 100644 index 0000000..0a0a2c7 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-08-external-db-configmap.yaml b/rhacs/4.5.2/central-services/templates/01-central-08-external-db-configmap.yaml new file mode 100644 index 0000000..48d2427 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-09-endpoints-config.yaml b/rhacs/4.5.2/central-services/templates/01-central-09-endpoints-config.yaml new file mode 100644 index 0000000..fa6204e --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-10-db-networkpolicy.yaml b/rhacs/4.5.2/central-services/templates/01-central-10-db-networkpolicy.yaml new file mode 100644 index 0000000..b33460d --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-10-db-networkpolicy.yaml @@ -0,0 +1,28 @@ +{{- include "srox.init" . -}} + +{{ if and ._rox.network.enableNetworkPolicies (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.5.2/central-services/templates/01-central-10-networkpolicy.yaml b/rhacs/4.5.2/central-services/templates/01-central-10-networkpolicy.yaml new file mode 100644 index 0000000..dcd5e03 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-10-networkpolicy.yaml @@ -0,0 +1,67 @@ +{{- include "srox.init" . -}} + +{{ if ._rox.network.enableNetworkPolicies }} +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 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/01-central-11-db-pvc.yaml b/rhacs/4.5.2/central-services/templates/01-central-11-db-pvc.yaml new file mode 100644 index 0000000..72763bf --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-11-db-pvc.yaml @@ -0,0 +1,64 @@ +{{- 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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "persistentvolume" $pvName $annotations) | nindent 4 }} +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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "persistentvolumeclaim" $claimName $annotations) | nindent 4 }} +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/01-central-11-pvc.yaml b/rhacs/4.5.2/central-services/templates/01-central-11-pvc.yaml new file mode 100644 index 0000000..2ec1916 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-11-pvc.yaml @@ -0,0 +1,61 @@ +{{- 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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "persistentvolume" $pvName $annotations) | nindent 4 }} +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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "persistentvolumeclaim" $claimName $annotations) | nindent 4 }} +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/01-central-12-central-db.yaml b/rhacs/4.5.2/central-services/templates/01-central-12-central-db.yaml new file mode 100644 index 0000000..cab6600 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-12-central-db.yaml @@ -0,0 +1,206 @@ +{{- 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: + {{- $annotations := dict -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "nonroot-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "central-db" $annotations) | nindent 8 }} + spec: + {{- if ._rox.central.db._nodeSelector }} + nodeSelector: + {{- ._rox.central.db._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.central.db.hostAliases }} + hostAliases: {{ toYaml ._rox.central.db.hostAliases | 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 + {{- if ._rox.central.db.priorityClassName }} + priorityClassName: {{ ._rox.central.db.priorityClassName }} + {{- end }} + 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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_secret" $annotations) -}} + {{- include "srox.annotations" (list . "secret" "central-db-password" $annotations) | nindent 4 }} +type: Opaque +stringData: + password: | + {{- ._rox.central.db._password.value | nindent 4 }} +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/01-central-13-deployment.yaml b/rhacs/4.5.2/central-services/templates/01-central-13-deployment.yaml new file mode 100644 index 0000000..8bb04ec --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/01-central-13-deployment.yaml @@ -0,0 +1,308 @@ +{{- 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + 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 }} + {{- if ._rox.central.priorityClassName }} + priorityClassName: {{ ._rox.central.priorityClassName }} + {{- end }} + {{- if ._rox.central.hostAliases }} + hostAliases: {{ toYaml ._rox.central.hostAliases | nindent 8 }} + {{- end }} + 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: ROX_MEMLIMIT + 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 telemetry.enabled is true or null, configure the endpoint and + the key, if provided. Also, configure additional listening endpoints.*/}} + {{- 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 }} + - name: ROX_TELEMETRY_API_WHITELIST + value: "/api/splunk/ta/*,/v1/auth/m2m/exchange,/api/cli/download/*" + {{- /* Otherwise... */}} + {{- else }} + {{- /* ... if telemetry.enabled is false, configure the key to disable + telemetry collection */}} + - name: ROX_TELEMETRY_STORAGE_KEY_V1 + value: "DISABLED" + {{- 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 }} + {{- if ._rox._scannerV4Enabled }} + - name: ROX_SCANNER_V4 + value: "true" + {{- end }} + {{- 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.env.openshift }} + - name: central-bound-sa-token + mountPath: /var/run/secrets/openshift/serviceaccount + readOnly: true + {{- end }} + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: central-encryption-key-chain + mountPath: /run/secrets/stackrox.io/central-encryption-key-chain + {{- 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.env.openshift }} + - name: central-bound-sa-token + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + path: token + audience: openshift + expirationSeconds: 3600 + {{- end }} + {{- if ._rox.central.notifierSecretsEncryption }} + {{- if ._rox.central.notifierSecretsEncryption.enabled }} + - name: central-encryption-key-chain + secret: + secretName: central-encryption-key-chain + {{- 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 + {{- 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.5.2/central-services/templates/01-central-14-service.yaml b/rhacs/4.5.2/central-services/templates/01-central-14-service.yaml new file mode 100644 index 0000000..f459fd7 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/01-central-15-exposure.yaml b/rhacs/4.5.2/central-services/templates/01-central-15-exposure.yaml new file mode 100644 index 0000000..9bfdbbb --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/02-scanner-00-serviceaccount.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-00-serviceaccount.yaml new file mode 100644 index 0000000..a27c602 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/02-scanner-01-psps.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-01-psps.yaml new file mode 100644 index 0000000..23b398c --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/02-scanner-01-security.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-01-security.yaml new file mode 100644 index 0000000..05ff6f1 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-01-security.yaml @@ -0,0 +1,45 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable }} + +{{- if ._rox.env.openshift }} +--- +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: + - nonroot-v2 + 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.5.2/central-services/templates/02-scanner-02-db-password-secret.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-02-db-password-secret.yaml new file mode 100644 index 0000000..c6c0bc1 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/02-scanner-03-tls-secret.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-03-tls-secret.yaml new file mode 100644 index 0000000..7c590ff --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/02-scanner-04-scanner-config.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-04-scanner-config.yaml new file mode 100644 index 0000000..4ed16c7 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/02-scanner-05-network-policy.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-05-network-policy.yaml new file mode 100644 index 0000000..a61b59e --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-05-network-policy.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies -}} +{{- 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 + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP + 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 }} +{{ end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-06-deployment.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-06-deployment.yaml new file mode 100644 index 0000000..6bbe53c --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-06-deployment.yaml @@ -0,0 +1,318 @@ +{{- 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scanner._nodeSelector }} + nodeSelector: + {{- ._rox.scanner._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.tolerations }} + tolerations: + {{- toYaml ._rox.scanner.tolerations | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.hostAliases }} + hostAliases: {{ toYaml ._rox.scanner.hostAliases | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scanner.affinity | nindent 8 }} + {{- if ._rox.scanner.priorityClassName }} + priorityClassName: {{ ._rox.scanner.priorityClassName }} + {{- end }} + 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: ROX_MEMLIMIT + 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 + {{- if eq ._rox.scanner.mode "slim" }} + secretName: additional-ca-sensor + {{- else }} + secretName: additional-ca + {{- end }} + - 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scanner._dbNodeSelector }} + nodeSelector: + {{- ._rox.scanner._dbNodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.dbHostAliases }} + hostAliases: {{ toYaml ._rox.scanner.dbHostAliases | 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 + {{- if ._rox.scanner.dbPriorityClassName }} + priorityClassName: {{ ._rox.scanner.dbPriorityClassName }} + {{- end }} + 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.5.2/central-services/templates/02-scanner-07-service.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-07-service.yaml new file mode 100644 index 0000000..2f65b15 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/02-scanner-08-hpa.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-08-hpa.yaml new file mode 100644 index 0000000..c7af476 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/02-scanner-v4-00-serviceaccount.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-00-serviceaccount.yaml new file mode 100644 index 0000000..91e4c8e --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-00-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} +{{- if (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: scanner-v4 + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "scanner-v4") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "scanner-v4") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-01-psps.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-01-psps.yaml new file mode 100644 index 0000000..14e38b4 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-01-psps.yaml @@ -0,0 +1,72 @@ +{{- include "srox.init" . -}} +{{- if and (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-scanner-v4-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-scanner-v4-psp") | nindent 4 }} +rules: +- apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4") }} + verbs: + - use + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-scanner-v4-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-scanner-v4-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-scanner-v4-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4-psp") }} +subjects: +- kind: ServiceAccount + name: scanner-v4 + namespace: {{ .Release.Namespace }} + +--- + +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-scanner-v4") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-scanner-v4") | 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.5.2/central-services/templates/02-scanner-v4-01-security.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-01-security.yaml new file mode 100644 index 0000000..d76329c --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-01-security.yaml @@ -0,0 +1,51 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled }} + {{- if ._rox.env.openshift }} + {{- if eq ._rox.env.openshift 3 }} + {{ include "srox.warn" (list . "On OpenShift 3.x no SecurityContextConstraint will be configured for Scanner V4.") }} + {{- else }} + {{/* Use a default SCC that ships with OpenShift 4.x. + We only need to create a Role and a RoleBinding for + associating the SCC with the Scanner V4 deployment. */}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-scanner-v4-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-scanner-v4-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-scanner-v4-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - nonroot-v2 + verbs: + - use + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: scanner-v4-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "scanner-v4-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "scanner-v4-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-scanner-v4-scc +subjects: +- kind: ServiceAccount + name: scanner-v4 + namespace: {{ .Release.Namespace }} + {{- end }} + {{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-02-db-password-secret.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-02-db-password-secret.yaml new file mode 100644 index 0000000..a382d3e --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-02-db-password-secret.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} +{{- /* The (...) below safe-guard against nil pointer evaluations for Helm versions built with Go < 1.18. */}} +{{- if and ._rox.scannerV4._dbEnabled (not (kindIs "invalid" (._rox.scannerV4.db._password).value)) }} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.scannerV4.db._password.value | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-03-db-tls-secret.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-03-db-tls-secret.yaml new file mode 100644 index 0000000..769f852 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-03-db-tls-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._dbEnabled ._rox.scannerV4.db._serviceTLS ._rox._ca }} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-db-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-db-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-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.scannerV4.db._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scannerV4.db._serviceTLS.Key | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-03-indexer-tls-secret.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-03-indexer-tls-secret.yaml new file mode 100644 index 0000000..c0e2a92 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-03-indexer-tls-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled ._rox.scannerV4.indexer._serviceTLS ._rox._ca }} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-indexer-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-indexer-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-indexer-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.scannerV4.indexer._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scannerV4.indexer._serviceTLS.Key | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-03-matcher-tls-secret.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-03-matcher-tls-secret.yaml new file mode 100644 index 0000000..cdc4d9f --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-03-matcher-tls-secret.yaml @@ -0,0 +1,22 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._matcherEnabled ._rox.scannerV4.matcher._serviceTLS ._rox._ca -}} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-matcher-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-matcher-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-matcher-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.scannerV4.matcher._serviceTLS.Cert | nindent 4 }} + key.pem: | + {{- ._rox.scannerV4.matcher._serviceTLS.Key | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-04-db-config.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-04-db-config.yaml new file mode 100644 index 0000000..439cfe8 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-04-db-config.yaml @@ -0,0 +1,17 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-db-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-db-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-db-config") | nindent 4 }} +data: + postgresql.conf: | + {{- ._rox.scannerV4.db._postgresConfig | nindent 4 }} + pg_hba.conf: | + {{- ._rox.scannerV4.db._hbaConfig | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-04-indexer-config.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-04-indexer-config.yaml new file mode 100644 index 0000000..26705b8 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-04-indexer-config.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-indexer-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-indexer-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-indexer-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner-v4/indexer-config.yaml.tpl") . | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-04-matcher-config.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-04-matcher-config.yaml new file mode 100644 index 0000000..6704367 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-04-matcher-config.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._matcherEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-matcher-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-matcher-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-matcher-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner-v4/matcher-config.yaml.tpl") . | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-05-db-network-policy.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-05-db-network-policy.yaml new file mode 100644 index 0000000..875aba8 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-05-db-network-policy.yaml @@ -0,0 +1,39 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-db") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-db + ingress: +{{- if ._rox.scannerV4._indexerEnabled }} + - from: + - podSelector: + matchLabels: + app: scanner-v4-indexer + ports: + - port: 5432 + protocol: TCP +{{- end }} +{{- if ._rox.scannerV4._matcherEnabled }} + - from: + - podSelector: + matchLabels: + app: scanner-v4-matcher + ports: + - port: 5432 + protocol: TCP + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-05-indexer-network-policy.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-05-indexer-network-policy.yaml new file mode 100644 index 0000000..460801a --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-05-indexer-network-policy.yaml @@ -0,0 +1,90 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-indexer + ingress: + {{- if ._rox.env.centralServices }} + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8443 + protocol: TCP + - from: + - podSelector: + matchLabels: + app: scanner-v4-matcher + ports: + - port: 8443 + protocol: TCP + {{- end }} + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8443 + protocol: TCP + policyTypes: + - Ingress + +{{- if ._rox.scannerV4.exposeMonitoring }} +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: {{ ._rox.scannerV4.indexer.metricsPort }} + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-indexer + policyTypes: + - Ingress +{{- end }} +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer-monitoring-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-indexer + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-05-matcher-network-policy.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-05-matcher-network-policy.yaml new file mode 100644 index 0000000..fbc3525 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-05-matcher-network-policy.yaml @@ -0,0 +1,74 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._matcherEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-matcher + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-matcher") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-matcher") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-matcher + ingress: + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8443 + protocol: TCP + policyTypes: + - Ingress + +{{- if ._rox.scannerV4.exposeMonitoring }} +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-matcher-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-matcher-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-matcher-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: {{ ._rox.scannerV4.matcher.metricsPort }} + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-matcher + policyTypes: + - Ingress +{{- end }} +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-matcher-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-matcher-monitoring-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-matcher-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-matcher + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-06-db-pvc.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-06-db-pvc.yaml new file mode 100644 index 0000000..8b27634 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-06-db-pvc.yaml @@ -0,0 +1,66 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.scannerV4._dbEnabled }} + +{{- if ._rox.scannerV4.db.persistence._pvcCfg }} +{{- $pvcCfg := ._rox.scannerV4.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 }} +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: + # this is used for backwards compatibility for operator if there are PVCs without annotation + # owned by the operator it will assume they belong to the deprecated central-db + {{- $labels := dict "target.pvc.stackrox.io" "scanner-v4-db" -}} + {{- include "srox.labels" (list . "persistentvolumeclaim" "scanner-v4-db" $labels) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolumeclaim" "scanner-v4-db") | nindent 4 }} +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} + +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-07-db-deployment.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-07-db-deployment.yaml new file mode 100644 index 0000000..953cb1c --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-07-db-deployment.yaml @@ -0,0 +1,142 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-db + {{- include "srox.labels" (list . "deployment" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-db + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-db") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "5432" + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-db") | nindent 8 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scannerV4.db._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.db._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.db.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.db.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.db.affinity | nindent 8 }} + {{- if ._rox.scannerV4.db.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.db.hostAliases | nindent 8 }} + {{- end }} + serviceAccountName: scanner-v4 + terminationGracePeriodSeconds: 120 + initContainers: + - name: init-db + image: {{ ._rox.scannerV4.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + - name: POSTGRES_HOST_AUTH_METHOD + value: "scram-sha-256" + - name: POSTGRES_PASSWORD_FILE + value: "/run/secrets/stackrox.io/secrets/password" +{{- if ._rox.env.centralServices }} + - name: SCANNER_DB_INIT_BUNDLE_ENABLED + value: "true" +{{- end }} + command: + - init-entrypoint.sh + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: scanner-v4-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + resources: + {{- ._rox.scannerV4.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + containers: + - name: db + image: {{ ._rox.scannerV4.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + - name: POSTGRES_HOST_AUTH_METHOD + value: "scram-sha-256" + {{- include "srox.envVars" (list . "deployment" "scanner-v4-db" "db") | nindent 8 }} + ports: + - name: tcp-postgresql + containerPort: 5432 + 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.scannerV4.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: config-volume + mountPath: /etc/stackrox.d/config/ + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + - name: shared-memory + mountPath: /dev/shm + securityContext: + fsGroup: 70 + volumes: + - name: disk + {{- toYaml ._rox.scannerV4.db.persistence._volumeCfg | nindent 8 }} + - name: config-volume + configMap: + name: {{ default "scanner-v4-db-config" ._rox.scannerV4.db.configOverride }} + - name: scanner-db-tls-volume + secret: + secretName: scanner-v4-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-templates/scanner-v4-db/postgresql.conf.default */}} + sizeLimit: 750Mi + - name: scanner-v4-db-password + secret: + secretName: scanner-v4-db-password +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-07-indexer-deployment.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-07-indexer-deployment.yaml new file mode 100644 index 0000000..2be0860 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-07-indexer-deployment.yaml @@ -0,0 +1,174 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-indexer + {{- include "srox.labels" (list . "deployment" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-indexer") | nindent 4 }} +spec: + replicas: {{ ._rox.scannerV4.indexer.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-indexer + strategy: + type: RollingUpdate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-indexer + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-indexer") | nindent 8 }} + annotations: + {{- $annotations := dict "traffic.sidecar.istio.io/excludeInboundPorts" "8443" -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "nonroot-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-indexer" $annotations) | nindent 8 }} + spec: + {{- if ._rox.scannerV4.indexer._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.indexer._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.indexer.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.indexer.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.indexer.affinity | nindent 8 }} + {{- if ._rox.scannerV4.indexer.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.indexer.hostAliases | nindent 8 }} + {{- end }} + containers: + - name: indexer + image: {{ ._rox.scannerV4.indexer.image.fullRef | quote }} + env: + - name: ROX_MEMLIMIT + 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 }} + - name: ROX_METRICS_PORT + value: ":{{- ._rox.scannerV4.indexer.metricsPort -}}" + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + - name: ROX_SECURE_METRICS_PORT + value: ":9091" + {{- end }} + {{- include "srox.envVars" (list . "deployment" "scanner-v4-indexer" "indexer") | nindent 8 }} + resources: + {{- ._rox.scannerV4.indexer._resources | nindent 10 }} + command: + - entrypoint.sh + - --conf=/etc/scanner/config.yaml + ports: + - name: grpc + containerPort: 8443 + {{ if ._rox.scannerV4.exposeMonitoring -}} + - name: monitoring + containerPort: {{ ._rox.scannerV4.indexer.metricsPort }} + {{- end}} + {{- if ._rox.monitoring.openshift.enabled }} + - containerPort: 9091 + name: monitoring-tls + {{- end }} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsNonRoot: true + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /health/readiness + port: 9443 + periodSeconds: 5 + timeoutSeconds: 1 + volumeMounts: + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: etc-ssl-volume + mountPath: /etc/ssl + - name: etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: config-volume + mountPath: /etc/scanner + readOnly: true + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: tmp-volume + mountPath: /tmp + - name: db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner-v4 + volumes: + - name: additional-ca-volume + secret: + optional: true + {{- if ._rox.env.centralServices }} + secretName: additional-ca + {{- else }} + secretName: additional-ca-sensor + {{- end }} + - name: etc-ssl-volume + emptyDir: {} + - name: etc-pki-volume + emptyDir: {} + - name: tls-volume + secret: + secretName: scanner-v4-indexer-tls + - name: config-volume + configMap: + name: scanner-v4-indexer-config + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: tmp-volume + emptyDir: {} + - name: db-password + secret: + secretName: scanner-v4-db-password + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: scanner-v4-indexer-monitoring-tls + {{- end }} + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-07-matcher-deployment.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-07-matcher-deployment.yaml new file mode 100644 index 0000000..859ea76 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-07-matcher-deployment.yaml @@ -0,0 +1,171 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._matcherEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-matcher + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-matcher + {{- include "srox.labels" (list . "deployment" "scanner-v4-matcher") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-matcher") | nindent 4 }} +spec: + replicas: {{ ._rox.scannerV4.matcher.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-matcher + strategy: + type: RollingUpdate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-matcher + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-matcher") | nindent 8 }} + annotations: + {{- $annotations := dict "traffic.sidecar.istio.io/excludeInboundPorts" "8443" -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "nonroot-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-matcher" $annotations) | nindent 8 }} + spec: + {{- if ._rox.scannerV4.matcher._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.matcher._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.matcher.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.matcher.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.matcher.affinity | nindent 8 }} + {{- if ._rox.scannerV4.matcher.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.matcher.hostAliases | nindent 8 }} + {{- end }} + containers: + - name: matcher + image: {{ ._rox.scannerV4.matcher.image.fullRef | quote }} + env: + - name: ROX_MEMLIMIT + valueFrom: + resourceFieldRef: + {{- /* This is set to requests.memory on purpose in an attempt to minimize memory usage. */}} + resource: requests.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 }} + - name: ROX_METRICS_PORT + value: ":{{- ._rox.scannerV4.matcher.metricsPort -}}" + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + - name: ROX_SECURE_METRICS_PORT + value: ":9091" + {{- end }} + {{- include "srox.envVars" (list . "deployment" "scanner-v4-matcher" "matcher") | nindent 8 }} + resources: + {{- ._rox.scannerV4.matcher._resources | nindent 10 }} + command: + - entrypoint.sh + - --conf=/etc/scanner/config.yaml + ports: + - name: grpc + containerPort: 8443 + {{ if ._rox.scannerV4.exposeMonitoring -}} + - name: monitoring + containerPort: {{ ._rox.scannerV4.matcher.metricsPort }} + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - containerPort: 9091 + name: monitoring-tls + {{- end }} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsNonRoot: true + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /health/readiness + port: 9443 + periodSeconds: 5 + timeoutSeconds: 1 + volumeMounts: + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: etc-ssl-volume + mountPath: /etc/ssl + - name: etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: config-volume + mountPath: /etc/scanner + readOnly: true + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: tmp-volume + mountPath: /tmp + - name: db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner-v4 + volumes: + - name: additional-ca-volume + secret: + optional: true + secretName: additional-ca + - name: etc-ssl-volume + emptyDir: {} + - name: etc-pki-volume + emptyDir: {} + - name: tls-volume + secret: + secretName: scanner-v4-matcher-tls + - name: config-volume + configMap: + name: scanner-v4-matcher-config + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: tmp-volume + emptyDir: {} + - name: db-password + secret: + secretName: scanner-v4-db-password + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: scanner-v4-matcher-monitoring-tls + {{- end }} + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-08-db-service.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-08-db-service.yaml new file mode 100644 index 0000000..f36bf4d --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-08-db-service.yaml @@ -0,0 +1,43 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-db") | nindent 4 }} +spec: + type: ClusterIP + ports: + - name: tcp-db + port: 5432 + targetPort: 5432 + selector: + app: scanner-v4-db + +{{- if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-db-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-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-v4-db-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-db.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 5432 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-08-indexer-service.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-08-indexer-service.yaml new file mode 100644 index 0000000..7b3457b --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-08-indexer-service.yaml @@ -0,0 +1,55 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-indexer") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: scanner-v4-indexer-monitoring-tls + {{- end }} +spec: + selector: + app: scanner-v4-indexer + clusterIP: None + ports: + - name: grpc-scanner-v4-indexer + port: 8443 + targetPort: grpc + {{- if ._rox.scannerV4.exposeMonitoring }} + - name: monitoring + port: {{ ._rox.scannerV4.indexer.metricsPort }} + targetPort: monitoring + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: indexer-monitoring-tls + port: 9091 + targetPort: monitoring-tls + {{- end }} + +{{- if ._rox.env.istio }} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-indexer-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-indexer-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-v4-indexer-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-indexer.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8443 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-08-matcher-service.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-08-matcher-service.yaml new file mode 100644 index 0000000..739fa6c --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-08-matcher-service.yaml @@ -0,0 +1,55 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._matcherEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-matcher + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-matcher") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-matcher") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: scanner-v4-matcher-monitoring-tls + {{- end }} +spec: + selector: + app: scanner-v4-matcher + clusterIP: None + ports: + - name: grpc-scanner-v4-matcher + port: 8443 + targetPort: grpc + {{ if ._rox.scannerV4.exposeMonitoring -}} + - name: monitoring + port: {{ ._rox.scannerV4.matcher.metricsPort }} + targetPort: monitoring + {{- end }} + {{ if ._rox.monitoring.openshift.enabled -}} + - name: matcher-monitoring-tls + port: 9091 + targetPort: monitoring-tls + {{- end }} + +{{- if ._rox.env.istio }} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-matcher-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-matcher-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-v4-matcher-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-matcher.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8443 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-09-indexer-hpa.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-09-indexer-hpa.yaml new file mode 100644 index 0000000..91e4832 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-09-indexer-hpa.yaml @@ -0,0 +1,20 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled (not ._rox.scannerV4.indexer.autoscaling.disable) }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner-v4-indexer") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scannerV4.indexer.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scannerV4.indexer.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner-v4-indexer + targetCPUUtilizationPercentage: 150 +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/02-scanner-v4-09-matcher-hpa.yaml b/rhacs/4.5.2/central-services/templates/02-scanner-v4-09-matcher-hpa.yaml new file mode 100644 index 0000000..d90bfcb --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/02-scanner-v4-09-matcher-hpa.yaml @@ -0,0 +1,20 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._matcherEnabled (not ._rox.scannerV4.matcher.autoscaling.disable) }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner-v4-matcher + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner-v4-matcher") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner-v4-matcher") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scannerV4.matcher.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scannerV4.matcher.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner-v4-matcher + targetCPUUtilizationPercentage: 150 +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/99-generated-values-secret.yaml b/rhacs/4.5.2/central-services/templates/99-generated-values-secret.yaml new file mode 100644 index 0000000..b3499e8 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/99-openshift-monitoring.yaml b/rhacs/4.5.2/central-services/templates/99-openshift-monitoring.yaml new file mode 100644 index 0000000..a2a6f28 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/99-openshift-monitoring.yaml @@ -0,0 +1,149 @@ +{{- 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 + +--- + +{{- /* +The ServiceMonitor is placed into the openshift-monitoring namespace to comply with the +OpenShift monitoring namespace label requirements. This is an exception to the rule +that leaking resources into system namespaces should be avoided. +*/}} +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 }}" + +--- + +{{- /* +TODO(ROX-22188): Switch to a ClusterRoleBinding to avoid leaking to kube-system 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 }}" + +--- + +{{- /* +The PrometheusRule is placed into the openshift-monitoring namespace to comply with the +OpenShift monitoring namespace label requirements. This is an exception to the rule +that leaking resources into system namespaces should be avoided. +Note that we have an exception for this resource for the SRE webhook validation for +managed OpenShift clusters. +*/}} +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.5.2/central-services/templates/99-shared-openshift-monitoring.yaml b/rhacs/4.5.2/central-services/templates/99-shared-openshift-monitoring.yaml new file mode 100644 index 0000000..2035970 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/99-shared-openshift-monitoring.yaml @@ -0,0 +1,65 @@ +{{- include "srox.init" . -}} +{{- if ._rox.monitoring.openshift.enabled -}} + {{- if (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: "scanner-v4-monitor-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "servicemonitor" (print "scanner-v4-monitor-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "servicemonitor" (print "scanner-v4-monitor-" .Release.Namespace)) | nindent 4 }} +spec: + endpoints: + {{- if ._rox.scannerV4._indexerEnabled }} + - interval: 30s + path: metrics + port: indexer-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: "scanner-v4-indexer.{{ .Release.Namespace }}.svc" + {{- end }} + {{- if ._rox.scannerV4._matcherEnabled }} + - interval: 30s + path: metrics + port: matcher-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: "scanner-v4-matcher.{{ .Release.Namespace }}.svc" + {{- end }} + selector: + matchLabels: + app.kubernetes.io/component: scanner-v4 + namespaceSelector: + matchNames: + - "{{ .Release.Namespace }}" +--- +{{/* TODO(ROX-22188): Switch to a ClusterRoleBinding to avoid leaking to + kube-system namespace. */ -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "rhacs-scanner-v4-auth-reader-{{ .Release.Namespace }}" + namespace: kube-system + labels: + {{- include "srox.labels" (list . "rolebinding" (print "rhacs-scanner-v4-auth-reader-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" (print "rhacs-scanner-v4-auth-reader-" .Release.Namespace)) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: scanner-v4 + namespace: "{{ .Release.Namespace }}" + {{- end }} +{{- end }} diff --git a/rhacs/4.5.2/central-services/templates/NOTES.txt b/rhacs/4.5.2/central-services/templates/NOTES.txt new file mode 100644 index 0000000..9f07746 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/NOTES.txt @@ -0,0 +1,68 @@ +{{- $_ := include "srox.init" . -}} + +StackRox Central Services has been installed. + + +Central Services Configuration Summary: + + Stackrox Version: {{ .Chart.AppVersion }} + Kubernetes Version: {{ ._rox._apiServer.version }} + Kubernetes Namespace: {{ .Release.Namespace }} + Helm Release Name: {{ .Release.Name }} + OpenShift Cluster: {{ if eq ._rox.env.openshift 0 -}} false {{ else -}} {{ ._rox.env.openshift }} {{ end }} + Scanner V4: {{ if ._rox._scannerV4Enabled -}} enabled {{- else -}} disabled {{- end }} +{{- if and ._rox._scannerV4Enabled ._rox._scannerV4Volume }} + Scanner V4 DB Volume: {{ ._rox._scannerV4Volume }} +{{- end }} + +{{ 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.5.2/central-services/templates/_central_endpoints.tpl b/rhacs/4.5.2/central-services/templates/_central_endpoints.tpl new file mode 100644 index 0000000..646d9a6 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_central_setup.tpl b/rhacs/4.5.2/central-services/templates/_central_setup.tpl new file mode 100644 index 0000000..e3e8b5f --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_central_setup.tpl @@ -0,0 +1,146 @@ +{{/* + 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 }} + {{ if $pvcCfg.storageClass}} + {{ $_ = set $._rox._state "referencedStorageClasses" (mustAppend $._rox._state.referencedStorageClasses $pvcCfg.storageClass | uniq) }} + {{ 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 }} + {{ if $dbPVCCfg.storageClass}} + {{ $_ = set $._rox._state "referencedStorageClasses" (mustAppend $._rox._state.referencedStorageClasses $dbPVCCfg.storageClass | uniq) }} + {{ 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.5.2/central-services/templates/_crypto.tpl b/rhacs/4.5.2/central-services/templates/_crypto.tpl new file mode 100644 index 0000000..4ac1fac --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_crypto.tpl @@ -0,0 +1,247 @@ +{{/* + 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 }} + {{ $msg := list }} + {{ $msg = append $msg (printf "Tried to generate certificate for %s, but no CA certificate is available." $spec.CN) }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "Providing the CA is required when certificates for new components need to be issued. This can happen, for instance, when enabling a new component such as Scanner V4 using 'helm upgrade'." }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "If the CA was generated by the Helm chart during initial installation, you need to retrieve these auto-generated values from the cluster and provide them to the 'helm upgrade' command. A command for retrieving the auto-generated values was included in the post-installation notes of the central-services Helm chart." }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "If the CA was generated outside of the Helm chart and provided during the installation of the central-services chart, then the same must be done when executing 'helm upgrade'. This can be achieved conveniently by specifying the '--reuse-values' flag to 'helm upgrade'." }} + {{ include "srox.fail" (join "\n" $msg) }} + {{ 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.5.2/central-services/templates/_dict.tpl b/rhacs/4.5.2/central-services/templates/_dict.tpl new file mode 100644 index 0000000..bf14a6d --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_expand.tpl b/rhacs/4.5.2/central-services/templates/_expand.tpl new file mode 100644 index 0000000..9ed2531 --- /dev/null +++ b/rhacs/4.5.2/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 assumed 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._expandSingle $ $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.5.2/central-services/templates/_format.tpl b/rhacs/4.5.2/central-services/templates/_format.tpl new file mode 100644 index 0000000..745fe47 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_helpers.tpl b/rhacs/4.5.2/central-services/templates/_helpers.tpl new file mode 100644 index 0000000..69e5316 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_helpers.tpl @@ -0,0 +1,94 @@ +{{/* + 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 -}} + +{{- define "srox.checkVersionRequirements" -}} + {{- $minHelmVersion := "3.9.0" -}} + {{- $ := . -}} + + {{- $helmVersion := "" -}} + {{- if and (not (kindIs "invalid" $.Capabilities.HelmVersion)) $.Capabilities.HelmVersion -}} + {{- $helmVersion = $.Capabilities.HelmVersion.Version -}} + {{- end -}} + + {{- if empty $helmVersion -}} + {{- $msg := printf "Failed to retrieve Helm version. Please make sure you are running Helm >= v%s." $minHelmVersion -}} + {{- if $._rox.allowUnsupportedHelmVersion -}} + {{- include "srox.warn" (list $ $msg) -}} + {{- else -}} + {{- include "srox.fail" $msg -}} + {{- end -}} + {{- else if semverCompare (printf "< %s" $minHelmVersion) $helmVersion -}} + {{- $msg := printf "Helm version requirements not satisfied. Your Helm %s is too old. Please update to Helm >= v%s." $helmVersion $minHelmVersion -}} + {{- if $._rox.allowUnsupportedHelmVersion -}} + {{- include "srox.warn" (list $ $msg) -}} + {{- else -}} + {{- include "srox.fail" $msg -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/rhacs/4.5.2/central-services/templates/_image-pull-secrets.tpl b/rhacs/4.5.2/central-services/templates/_image-pull-secrets.tpl new file mode 100644 index 0000000..e758a70 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_image-pull-secrets.tpl @@ -0,0 +1,105 @@ +{{/* + srox.configureImagePullSecrets $ $cfgName $imagePullSecrets $secretResourceName $defaultSecretNames $namespace + + Configures image pull secrets. + + Note: This function must be called late in srox.init, as we rely on "srox.configureImage" to collect the + set of all referenced images first. + + This function enriches $imagePullSecrets based on the exposed configuration parameters to contain: + + 1. Optionally (i.e. only if $imagePullSecrets contains a username), a `_dockerAuths` field, containing a map + from registry URLs to settings that contain login credentials. + The map contains registries for all images passed so far to srox.configureImage invocations. + + 2. A `_names` field, containing a list of Kubernetes secret names. The chart templates then use this field + to populate imagePullSecrets lists in ServiceAccount objects. + + The list contains the following secrets: + + - Secrets referenced via $imagePullSecrets.useExisting (unconditonally). + - Image pull secrets associated with the default service account (unless + $imagePullSecrets.useFromDefaultServiceAccount was set to false by the user). + - $secretResourceName, i.e. the secret optionally created by the chart templates. This name will be included + in the list either if username/password is provided (i.e. whe the chart ensures presence of the secret) OR + if the resource already exists in the namespace (for backward compatibility with versions 4.3 or earlier). + - $defaultSecretNames, only if the corresponding secrets already exist in the namespace (again, for backward + compatibility). + + Additionally, this function fails execution if the list resulting from first three bullet points + combined is empty. + +*/}} + +{{ 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 }} + +{{ if $imagePullSecrets._username }} + {{/* When username is present, existence of $secretResourceName will be assured by the templates; add to the list. */}} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretResourceName }} + + {{ $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 }} + +{{ 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 }} + +{{/* For backward compatibility, include those secrets which already exist. + In manifest installation mode, include them unconditionally, for lack of a better way. +*/}} +{{ range $secretName := append $defaultSecretNames $secretResourceName }} + {{ $secret := dict }} + {{ include "srox.safeLookup" (list $ $secret "v1" "Secret" $namespace $secretName) }} + {{ if or (eq $._rox.env.installMethod "manifest") $secret.result }} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretName }} + {{ end }} +{{ end }} + +{{ $imagePullSecretNames = $imagePullSecretNames | uniq | sortAlpha }} +{{ $_ := set $imagePullSecrets "_names" $imagePullSecretNames }} + +{{ end }} diff --git a/rhacs/4.5.2/central-services/templates/_images.tpl b/rhacs/4.5.2/central-services/templates/_images.tpl new file mode 100644 index 0000000..dced29d --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_init.tpl b/rhacs/4.5.2/central-services/templates/_init.tpl new file mode 100644 index 0000000..6e6ab38 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_init.tpl @@ -0,0 +1,310 @@ +{{/* + 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 }} +{{ $_ = set $state "customCertGen" false }} +{{ $_ = set $state "generated" dict }} +{{ $_ = set $state "generatedName" $generatedName }} +{{ $_ = set $state "notes" list }} +{{ $_ = set $state "warnings" list }} +{{ $_ = set $state "referencedImages" dict }} +{{ $_ = set $state "referencedStorageClasses" list }} +{{ $_ = set $._rox "_state" $state }} + +{{- include "srox.checkVersionRequirements" $ -}} + +{{ $configShape := $.Files.Get "internal/config-shape.yaml" | fromYaml }} +{{ $configShapeScanner := $.Files.Get "internal/scanner-config-shape.yaml" | fromYaml }} +{{ $_ = include "srox.mergeInto" (list $configShape $configShapeScanner) }} +{{ $configShapeScannerV4 := $.Files.Get "internal/scanner-v4-config-shape.yaml" | fromYaml }} +{{ $_ = include "srox.mergeInto" (list $configShape $configShapeScannerV4) }} + +{{ $_ = include "srox.mergeInto" (list $rox $configShape (tpl ($.Files.Get "internal/bootstrap-defaults.yaml.tpl") . | fromYaml)) }} + +{{ $_ = set $._rox "_configShape" $configShape }} + +{{ $_ = include "srox.loadAnnotationTemplates" $ }} + +{{/* + 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 $) }} + +{{ include "srox.setInstallMethod" (list $) }} + +{{/* 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) }} + +{{/* Add environment information which should not be modifiable by the user. */}} +{{ $_ := set $env "centralServices" true }} + +{{/* 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 }} + +{{/* + ScannerV4 setup. + */}} + +{{ $scannerV4Cfg := $._rox.scannerV4 }} +{{ include "srox.scannerV4Init" (list $ $scannerV4Cfg) }} + +{{ if $._rox.scannerV4._dbEnabled }} + {{ include "srox.scannerV4Volume" $ }} +{{ 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. + + Note: This must happen late, as we rely on "srox.configureImage" to collect the + set of all referenced images first. + + 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) }} + +{{/* 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.5.2/central-services/templates/_injected-ca-bundle.tpl b/rhacs/4.5.2/central-services/templates/_injected-ca-bundle.tpl new file mode 100644 index 0000000..f831139 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_labels.tpl b/rhacs/4.5.2/central-services/templates/_labels.tpl new file mode 100644 index 0000000..703c8ae --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_labels.tpl @@ -0,0 +1,31 @@ +{{/* + srox._labels $ $labels $extraLabels $objType $objName $forPod + + Writes all applicable [pod] labels (including default labels) for $objType/$objName + into $labels. Pod labels are written iff $forPod is true. + The dict $extraLabels can be used for specifying additional labels which + can be modified by the user using `customize` entries before before they are added to $labels. + */}} +{{ define "srox._labels" }} +{{ $ := index . 0 }} +{{ $labels := index . 1 }} +{{ $extraLabels := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $forPod := index . 5 }} +{{ $_ := 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-z0-9-]+)-\\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 $extraLabels $objType $objName $metadataNames) }} +{{ end }} diff --git a/rhacs/4.5.2/central-services/templates/_lookup.tpl b/rhacs/4.5.2/central-services/templates/_lookup.tpl new file mode 100644 index 0000000..2dc0aa9 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_metadata.tpl b/rhacs/4.5.2/central-services/templates/_metadata.tpl new file mode 100644 index 0000000..e97d70d --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_metadata.tpl @@ -0,0 +1,307 @@ +{{/* + srox.labels $ $objType $objName [ $extraLabels ] + + Format labels for $objType/$objName as YAML. This takes into consideration the $extraLabels, + if provided, plus labels added using the generic `customize` configuration mechanism. + Note that provided $extraLabels can be modified by the user via `customize`. + + Note that pod resources are treated specially when it comes to customizing labels. + For enabling the user to define labels which shall only be applied to pods belonging + to a specific workload, the following rules apply for the Helm chart templates: + + - use the "srox.podLabels" template for injecting labels into pod templates and + - use the "srox.labels" template for injecting labels into all other resources. + + The user of the Helm charts may define `labels` within the `customize` structure for any + resources rendered as part of the charts. Such labels defined for workloads, e.g. a deployment, + will be injected into the deployment resource *and* will also be inherited to the pods belonging + to the workload. On the other hand, labels defined via `podLabels` are only meaningful for workload + resources and are only injected into the respective pods. + */}} +{{- define "srox.labels" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraLabels := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraLabels = default dict (index . 3) -}} + {{- end -}} + {{- $labels := dict -}} + {{- $_ := include "srox._labels" (list $ $labels $extraLabels $objType $objName false) }} + {{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.podLabels $ $objType $objName [ $extraLabels ] + + Format pod labels for $objType/$objName as YAML. This takes into consideration the $extraLabels, + if provided, plus labels added using the generic `customize` configuration mechanism. + Note that provided $extraLabels can be modified by the user via `customize`. + + See the description above for the template "srox.labels" for an explanation of the differences between + "srox.labels" and "srox.podLabels". + */}} +{{- define "srox.podLabels" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraLabels := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraLabels = default dict (index . 3) -}} + {{- end -}} + {{- $labels := dict -}} + {{- $_ := include "srox._labels" (list $ $labels $extraLabels $objType $objName true) }} + {{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.annotations $ $objType $objName [ $extraAnnotations ] + + Format annotations for $objType/$objName as YAML. This takes into consideration the $extraAnnotations, + if provided, plus annotations added using the generic `customize` configuration mechanism. + Note that provided $extraAnnotations can be modified by the user via `customize`. + + Note that pod resources are treated specially when it comes to customizing annotations. + For enabling the user to define annotations which shall only be applied to pods belonging + to a specific workload, the following rules apply for the Helm chart templates: + + - use the "srox.podAnnotations" template for injecting annotations into pod templates and + - use the "srox.annotations" template for injecting annotations into all other resources. + + The user of the Helm charts may define `annotations` within the `customize` structure for any + resources rendered as part of the charts. Such annotations defined for workloads, e.g. a deployment, + will be injected into the deployment resource *and* will also be inherited to the pods belonging + to the workload. On the other hand, annotations defined via `podAnnotations` are only meaningful + for workload resources and are only injected into the respective pods. + */}} +{{- define "srox.annotations" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraAnnotations := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraAnnotations = default dict (index . 3) -}} + {{- end -}} + {{- $annotations := dict -}} + {{- $_ := include "srox._annotations" (list $ $annotations $extraAnnotations $objType $objName false) -}} + {{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.podAnnotations $ $objType $objName [ $extraAnnotations ] + + Format pod annotations for $objType/$objName as YAML. This takes into consideration the $extraAnnotations, + if provided, plus annotations added using the generic `customize` configuration mechanism. + Note that provided $extraAnnotations can be modified by the user via `customize`. + + See the description above for the template "srox.annotations" for an explanation of the differences between + "srox.annotations" and "srox.podAnnotations". + */}} +{{- define "srox.podAnnotations" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraAnnotations := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraAnnotations = default dict (index . 3) -}} + {{- end -}} + {{- $annotations := dict -}} + {{- $_ := include "srox._annotations" (list $ $annotations $extraAnnotations $objType $objName 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 $extraAnnotations $objType $objName $forPod + + Writes all applicable [pod] annotations (including default annotations) for + $objType/$objName into $annotations. Pod labels are written iff $forPod is true. + The dict $extraAnnotations can be used for specifying additional annotations which + can be modified by the user using `customize` entries before before they are added to $annotations. + */}} +{{ define "srox._annotations" }} +{{ $ := index . 0 }} +{{ $annotations := index . 1 }} +{{ $extraAnnotations := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $forPod := index . 5 }} +{{ $_ := 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 $extraAnnotations $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 dict $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 $extraMetadata $objType $objName $metadataNames + + Writes custom key/value metadata to $metadata by consulting $extraMetadata in addition to 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 }} +{{ $extraMetadata := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $metadataNames := index . 5 }} + +{{ $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 $extraMetadata $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. */ -}} + {{- if hasPrefix "stackrox-" $name -}} + {{- printf "%s-%s" $._rox.globalPrefix (trimPrefix "stackrox-" $name) -}} + {{- else if hasPrefix "stackrox:" $name -}} + {{- printf "%s:%s" $._rox.globalPrefix (trimPrefix "stackrox:" $name) -}} + {{- else -}} + {{- include "srox.fail" (printf "Unknown naming convention for global resource %q." $name) -}} + {{- end -}} +{{- 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 -}} + +{{/* + srox.getAnnotationTemplate . $name $out + + Retrieve the annotation template with the given $name and store it in the provided $out parameter. + */}} +{{ define "srox.getAnnotationTemplate" }} + {{ $ := index . 0 }} + {{ $name := index . 1 }} + {{ $out := index . 2 }} + {{ if kindIs "invalid" $._rox._annotationTemplates }} + {{ include "srox.fail" "Annotation templates not initialized" }} + {{ end }} + {{ $annotationTemplates := get $._rox._annotationTemplates $name }} + {{ if not $annotationTemplates }} + {{ include "srox.fail" (printf "Annotation template %q does not exist in internal/annotations/" $name) }} + {{ end }} + {{ range $key, $value := $annotationTemplates }} + {{ $_ := set $out $key $value }} + {{ end }} +{{ end }} + +{{/* + srox.loadAnnotationTemplates . + + Load the annotation templates from `internal/annotations` and store them within $._rox. + The templates can later be retrieved with `srox.getAnnotationTemplate`. + */}} +{{ define "srox.loadAnnotationTemplates" }} + {{ $ := . }} + {{ if kindIs "invalid" $._rox._annotationTemplates }} + {{ $_ := set $._rox "_annotationTemplates" dict }} + {{ end }} + {{ range $fileName, $annotations := $.Files.Glob "internal/annotations/*.yaml" }} + {{ $name := trimSuffix ".yaml" (base $fileName) }} + {{ $_ := set $._rox._annotationTemplates $name ($annotations | toString | fromYaml) }} + {{ end }} +{{ end }} diff --git a/rhacs/4.5.2/central-services/templates/_openshift.tpl b/rhacs/4.5.2/central-services/templates/_openshift.tpl new file mode 100644 index 0000000..85201cb --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_psp.tpl b/rhacs/4.5.2/central-services/templates/_psp.tpl new file mode 100644 index 0000000..bffb2a0 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_pvcs.tpl b/rhacs/4.5.2/central-services/templates/_pvcs.tpl new file mode 100644 index 0000000..ad40204 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_pvcs.tpl @@ -0,0 +1,20 @@ +{{/* + srox.getPVCs $ + + This function attempts to retrieve information about all available PVCs in the + current namespace + + $._rox.env.pvcs.names: A list of PVC names. + */}} +{{- define "srox.getPVCs" -}} + + {{- $ := index . 0 -}} + {{- $pvcNames := list -}} + {{- $lookupResult := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupResult "v1" "PersistentVolumeClaim" $._rox._namespace "") -}} + {{- range $pvc := get ($lookupResult.result | default dict) "items" | default list -}} + {{- $pvcNames = append $pvcNames $pvc.metadata.name -}} + {{- end -}} + {{- $_ := set $._rox.env.pvcs "names" $pvcNames -}} + +{{- end -}} diff --git a/rhacs/4.5.2/central-services/templates/_reporting.tpl b/rhacs/4.5.2/central-services/templates/_reporting.tpl new file mode 100644 index 0000000..621e284 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_scanner-v4_init.tpl b/rhacs/4.5.2/central-services/templates/_scanner-v4_init.tpl new file mode 100644 index 0000000..323bfa4 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_scanner-v4_init.tpl @@ -0,0 +1,179 @@ +{{/* + srox.scannerV4Init . $scannerV4Config + + Initializes the Scanner v4 configuration. The scanner chart has two modes: Indexer and Matcher. + In Indexer mode, the Scanner pulls images and analyzes them to determine the base OS and installed packages + (i.e. it indexes the images). + In Matcher mode, the Scanner matches the found packages to known vulnerabilities to produce a Vulnerability Report. + Both modes require access to a PostgreSQL database. + + StackRox's Central service has two Scanner deployments: a Scanner running in Indexer mode and another + running in Matcher mode. In this context, the Helm chart can create its own certificates. + + StackRox's Secured Cluster services may deploy the Scanner in Indexer mode, only. + This would be done to access registries inaccessible to the Central cluster. + In this context, the Helm chart does not generate its own certificates. + + $scannerV4Config contains all values which are configured by the user. The structures can be viewed in the respective + config-shape. See internal/scanner-v4-config-shape.yaml. + */}} + +{{ define "srox.scannerV4Init" }} + +{{ $ := index . 0 }} +{{ $scannerV4Cfg := index . 1 }} +{{ $_ := false }} + +{{/* Sanity check. */}} +{{- if not (or (eq $.Chart.Name "stackrox-central-services") (eq $.Chart.Name "stackrox-secured-cluster-services")) -}} + {{- include "srox.fail" (printf "Unexpected Helm chart name %q." $.Chart.Name) -}} +{{- end -}} + +{{ $componentsCentralChart := dict "indexer" true "matcher" true }} +{{ $componentsSecuredClusterChart := dict "indexer" true "matcher" false }} + +{{/* These will be propagated up. */}} +{{ $components := dict "indexer" false "matcher" false }} +{{ $dbEnabled := false }} + +{{- if not $scannerV4Cfg.disable }} + {{/* Scanner V4 is switched on. */}} + + {{/* Scanner V4 component configuration depends on the chart. */}} + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{- $components = $componentsCentralChart -}} + {{- else -}} + {{- $components = $componentsSecuredClusterChart -}} + {{/* scannerV4.indexer.disable can be used to disable the deployment of indexer. + This is required for the operator use-case. */}} + {{- if $scannerV4Cfg.indexer.disable -}} + {{- $_ = set $components "indexer" false -}} + {{- end -}} + {{- end -}} + + {{/* Configure images, certificates and passwords as required. */}} + {{ if or (get $components "indexer") (get $components "matcher") }} + {{ include "srox.configureImage" (list $ $scannerV4Cfg.image) }} + {{ end }} + + {{ if get $components "indexer" }} + {{ $_ := set $scannerV4Cfg.indexer "image" $scannerV4Cfg.image }} + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{/* Only generate certificate when installing central-services. + For secured-cluster-services we don't configure certificates here, + instead they will be distributed at runtime by Sensor and Central. */}} + {{- if kindIs "invalid" $._rox.scannerV4.indexer.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-indexer-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.indexer.serviceTLS "generate" true -}} + {{- end -}} + {{- end -}} + {{- end }} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_INDEXER_SERVICE: Scanner V4 Indexer" "dnsBase" "scanner-v4-indexer" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.indexer.serviceTLS" $cryptoSpec) }} + {{- end -}} + {{ end }} + + {{ if get $components "matcher" }} + {{ $_ := set $scannerV4Cfg.matcher "image" $scannerV4Cfg.image }} + {{- if kindIs "invalid" $._rox.scannerV4.matcher.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-matcher-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.matcher.serviceTLS "generate" true -}} + {{- end -}} + {{- end }} + {{- end }} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_MATCHER_SERVICE: Scanner V4 Matcher" "dnsBase" "scanner-v4-matcher" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.matcher.serviceTLS" $cryptoSpec) }} + {{ end }} + + {{ if or (get $components "indexer") (get $components "matcher") }} + {{- if kindIs "invalid" $._rox.scannerV4.db.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-db-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.db.serviceTLS "generate" true -}} + {{- end -}} + {{- end -}} + {{- end }} + {{- if kindIs "invalid" $._rox.scannerV4.db.password.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-db-password") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.db.password "generate" true -}} + {{- end -}} + {{- end }} + + {{ include "srox.configureImage" (list $ $scannerV4Cfg.db.image) }} + {{ include "srox.configurePassword" (list $ "scannerV4.db.password") }} + + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{/* Only generate certificate when installing central-services. */}} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_DB_SERVICE: Scanner V4 DB" "dnsBase" "scanner-v4-db" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.db.serviceTLS" $cryptoSpec) }} + {{- end -}} + {{ end }} + +{{- if eq $.Chart.Name "stackrox-secured-cluster-services" -}} + {{/* Special handling for the secured-cluster-services chart in case it gets deployed + to the same namespace as central-services. */}} + {{ $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-v4-indexer from this chart and configuring sensor to use existing scanner-v4-indexer instance, if any.") }} + {{ $_ := set $components "indexer" false }} + {{ end }} +{{- end }} + +{{- end -}} {{/* if not $scannerV4Cfg.disable */}} + +{{/* Propagate information about which Scanner V4 components to deploy. */}} +{{- $_ := set $._rox "_scannerV4Enabled" (not $scannerV4Cfg.disable) -}} +{{- $_ := set $._rox.scannerV4 "_indexerEnabled" (get $components "indexer") -}} +{{- $_ := set $._rox.scannerV4 "_matcherEnabled" (get $components "matcher") -}} +{{- if or (get $components "indexer") (get $components "matcher") -}} + {{- $_ := set $._rox.scannerV4 "_dbEnabled" true -}} +{{- end -}} + +{{/* Provide some human-readable feedback regarding the Scanner V4 configuration to the user installing the Helm chart. */}} +{{- if and (get $components "indexer") (not (get $components "matcher")) -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "indexer" -}} +{{- else if and (not (get $components "indexer")) (get $components "matcher") -}} + {{/* Just here for completeness, not allowed currently. */}} + {{- $_ = set $._rox.scannerV4 "_installMode" "matcher" -}} +{{- else if and (get $components "indexer") (get $components "matcher") -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "indexer and matcher" -}} +{{- else -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "" -}} +{{- end -}} + +{{- if not $scannerV4Cfg.disable }} + {{- if eq $._rox.scannerV4._installMode "" }} + {{ include "srox.note" (list $ (printf "Scanner V4 is enabled and Scanner V4 components are already deployed.")) }} + {{- else }} + {{ include "srox.note" (list $ (printf "Scanner V4 is enabled and the following Scanner V4 components will be deployed: %s" $._rox.scannerV4._installMode)) }} + {{- end }} +{{- end }} + +{{- end -}} diff --git a/rhacs/4.5.2/central-services/templates/_scanner-v4_volume.tpl b/rhacs/4.5.2/central-services/templates/_scanner-v4_volume.tpl new file mode 100644 index 0000000..4d2a14b --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_scanner-v4_volume.tpl @@ -0,0 +1,113 @@ +{{/* + srox.scannerV4Volume $ + + Configures and initializes Scanner v4 persistence. + */}} +{{ define "srox.scannerV4Volume" }} +{{ $ := . }} +{{ $_ := set $ "_rox" $._rox }} + +{{ $scannerV4DBCfg := $._rox.scannerV4.db }} + +{{/* + Scanner v4 DB Volume config setup. + */}} +{{ $scannerV4DBVolumeCfg := dict }} +{{ $scannerV4DBVolumeHumanReadable := "" }} +{{ $pvcConfigShape := $._rox._configShape.scannerV4.db.persistence.persistentVolumeClaim }} +{{ $pvcDefaults := dict }} +{{- if eq $.Chart.Name "stackrox-central-services" -}} + {{ $pvcDefaults = $._rox._defaults.scannerV4DBPVCDefaults }} +{{- else -}} + {{ $pvcDefaults = $._rox.scannerV4DBPVCDefaults }} +{{- end -}} + +{{ $extraSettings := dict "createClaim" .Release.IsInstall }} +{{ if $._rox.env.storageClasses.default }} + {{ $_ = set $extraSettings "storageClass" $._rox.env.storageClasses.default }} +{{ end }} + +{{/* First we check that the persistence configuration provided by the user is sane in the sense that only one of the + supported backends emptyDir/hostPath/PVC is configured. */}} +{{ $persistenceBackendsConfigured := list }} +{{ if $scannerV4DBCfg.persistence.none }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured "emptyDir" }} +{{ end }} +{{ if $scannerV4DBCfg.persistence.hostPath }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured "hostPath" }} +{{ end }} +{{ if not (deepEqual $pvcConfigShape $scannerV4DBCfg.persistence.persistentVolumeClaim) }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured (printf "PVC:%v" $scannerV4DBCfg.persistence.persistentVolumeClaim) }} +{{ end }} + +{{/* Sanity checks and defaulting. */}} +{{ if empty $persistenceBackendsConfigured }} + {{/* No persistence backend configured, pick a reasonable default. */}} + {{ if or $._rox.env.storageClasses.default (eq $.Chart.Name "stackrox-central-services") }} + {{/* Either a default StorageClass has been detected or we are currently rendering central-services. + In both cases we configure a PVC as persistence backend. */}} + {{ if $._rox.env.storageClasses.default }} + {{ include "srox.note" (list $ "Default StorageClass detected, a PVC will be used for Scanner V4 DB persistence.") }} + {{ else }} + {{ include "srox.note" (list $ "A PVC will be used for Scanner V4 DB persistence.") }} + {{ end }} + {{ if has $pvcDefaults.claimName $._rox.env.pvcs.names }} + {{ $_ = set $extraSettings "createClaim" false }} + {{ else }} + {{ $_ = set $extraSettings "createClaim" true }} + {{ end }} + {{ $_ = include "srox.mergeInto" (list $scannerV4DBCfg.persistence.persistentVolumeClaim $pvcConfigShape $extraSettings $pvcDefaults) }} + {{ else }} + {{/* No default StorageClass detected, currently rendering secured-cluster-services chart. */}} + {{ if has $pvcDefaults.claimName $._rox.env.pvcs.names }} + {{ include "srox.note" (list $ (printf "A PVC named %s already exists, will keep using it for Scanner V4 DB persistence." $pvcDefaults.claimName)) }} + {{ $_ = set $extraSettings "createClaim" false }} + {{ $_ = include "srox.mergeInto" (list $scannerV4DBCfg.persistence.persistentVolumeClaim $pvcConfigShape $extraSettings $pvcDefaults) }} + {{ else }} + {{/* Fallback to emptyDir. */}} + {{ include "srox.warn" (list $ (printf "No default StorageClass detected, using emptyDir as persistence backend for Scanner V4 DB. It is highly recommended to use a PVC instead. Please check the documentation for more information on this." )) }} + {{ $_ = set $scannerV4DBCfg.persistence "none" true }} + {{ end }} + {{ end }} +{{ else if gt (len $persistenceBackendsConfigured) 1 }} + {{ include "srox.fail" (printf "Invalid persistence configuration for Scanner V4 DB: more than one persistence backend configured (%v)" $persistenceBackendsConfigured) }} +{{ end }} + + +{{/* Update $scannerV4DBVolumeCfg depending on configured persistence backend. */}} +{{ if $scannerV4DBCfg.persistence.none }} + {{ include "srox.warn" (list $ "Persistence for Scanner V4 DB is turned off (it is using an emptyDir volume). Every deletion of the StackRox Scanner V4 DB pod will cause you to lose all your data. This is STRONGLY recommended against.") }} + {{ $_ := set $scannerV4DBVolumeCfg "emptyDir" dict }} + {{ $scannerV4DBVolumeHumanReadable = "emptyDir" }} +{{ else if $scannerV4DBCfg.persistence.hostPath }} + {{ if not $scannerV4DBCfg.nodeSelector }} + {{ include "srox.warn" (list $ "A hostPath volume will be used by the Scanner V4 DB. At the same time no node selector is specified. This is unlikely to work reliably.") }} + {{ end }} + {{ $_ := set $scannerV4DBVolumeCfg "hostPath" (dict "path" $scannerV4DBCfg.persistence.hostPath) }} + {{ $scannerV4DBVolumeHumanReadable = printf "hostPath (%s)" $scannerV4DBCfg.persistence.hostPath}} +{{ else }} + {{ if kindIs "invalid" $scannerV4DBCfg.persistence.persistentVolumeClaim.storageClass }} + {{ include "srox.note" (list $ "A PVC using the default storage class will be used for the Scanner V4 DB.") }} + {{ else }} + {{ include "srox.note" (list $ (printf "A PVC using the storage class %q will be used for the Scanner V4 DB." $scannerV4DBCfg.persistence.persistentVolumeClaim.storageClass)) }} + {{ end }} + {{ $scannerV4DBPVCCfg := $scannerV4DBCfg.persistence.persistentVolumeClaim }} + {{ $_ := include "srox.mergeInto" (list $scannerV4DBPVCCfg $extraSettings $pvcDefaults) }} + {{ $_ = set $scannerV4DBVolumeCfg "persistentVolumeClaim" (dict "claimName" $scannerV4DBPVCCfg.claimName) }} + {{ if $scannerV4DBPVCCfg.createClaim }} + {{ $_ = set $scannerV4DBCfg.persistence "_pvcCfg" $scannerV4DBPVCCfg }} + {{ end }} + {{ if $scannerV4DBPVCCfg.storageClass }} + {{ $_ = set $._rox._state "referencedStorageClasses" (mustAppend $._rox._state.referencedStorageClasses $scannerV4DBPVCCfg.storageClass | uniq) }} + {{ end }} + {{ $scannerV4DBVolumeHumanReadable = printf "PVC (%s)" $scannerV4DBPVCCfg.claimName }} +{{ end }} + +{{ $allPersistenceMethods := keys $scannerV4DBVolumeCfg | sortAlpha }} +{{ if ne (len $allPersistenceMethods) 1 }} +{{ end }} + +{{ $_ = set $scannerV4DBCfg.persistence "_volumeCfg" $scannerV4DBVolumeCfg }} +{{ $_ := set $._rox "_scannerV4Volume" $scannerV4DBVolumeHumanReadable }} + +{{ end }} diff --git a/rhacs/4.5.2/central-services/templates/_scanner_init.tpl b/rhacs/4.5.2/central-services/templates/_scanner_init.tpl new file mode 100644 index 0000000..75fbe95 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/central-services/templates/_set_install_method.tpl b/rhacs/4.5.2/central-services/templates/_set_install_method.tpl new file mode 100644 index 0000000..9475774 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_set_install_method.tpl @@ -0,0 +1,13 @@ +{{/* + srox.setInstallMethod $ + + Sets $.env.installMethod to one of: "operator", "helm", "manifest". +*/}} + +{{ define "srox.setInstallMethod" }} +{{ $ := index . 0 }} + + +{{ $_ := set $._rox.env "installMethod" "helm" }} + +{{ end }} diff --git a/rhacs/4.5.2/central-services/templates/_storage_classes.tpl b/rhacs/4.5.2/central-services/templates/_storage_classes.tpl new file mode 100644 index 0000000..9183999 --- /dev/null +++ b/rhacs/4.5.2/central-services/templates/_storage_classes.tpl @@ -0,0 +1,36 @@ +{{/* + srox.getStorageClasses $ + + This function attempts to retrieve information about all available StorageClasses on the + cluster and write it to + + $._rox.env.storageClasses.all: A dict mapping storage class names to dicts containing + relevant properties of the storage class. + + $._rox.env.storageClasses.default: Either nil or a string containing the name of the + default StorageClass. + */}} +{{- define "srox.getStorageClasses" -}} + + {{- $ := index . 0 -}} + {{- $storageClasses := dict -}} + {{- $defaultStorageClass := "" -}} + + {{- $lookupResult := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupResult "storage.k8s.io/v1" "StorageClass" "" "") -}} + {{- range $sc := get ($lookupResult.result | default dict) "items" | default list -}} + {{- $storageClassName := $sc.metadata.name -}} + {{- $annotations := $sc.metadata.annotations | default dict -}} + {{- $isDefault := index $annotations "storageclass.kubernetes.io/is-default-class" | default false -}} + {{- $_ := set $storageClasses $storageClassName (dict "isDefault" $isDefault) -}} + {{- if and $isDefault (not $defaultStorageClass) -}} + {{- $defaultStorageClass = $storageClassName -}} + {{- end -}} + {{- end -}} + + {{ $_ := set $._rox.env.storageClasses "all" $storageClasses }} + {{- if ne $defaultStorageClass "" -}} + {{- $_ := set $._rox.env.storageClasses "default" $defaultStorageClass -}} + {{- end -}} + +{{- end -}} diff --git a/rhacs/4.5.2/central-services/values-private.yaml.example b/rhacs/4.5.2/central-services/values-private.yaml.example new file mode 100644 index 0000000..8576ca8 --- /dev/null +++ b/rhacs/4.5.2/central-services/values-private.yaml.example @@ -0,0 +1,224 @@ +# 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 Scanner 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----- +# +# # Secret configuration options for the Scanner V4 deployment. +# scannerV4: +# indexer: +# # Internal "scanner-v4-indexer..svc" service TLS certificate for the Scanner V4 indexer 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----- +# +# matcher: +# # Internal "scanner-v4-matcher..svc" service TLS certificate for the Scanner V4 matcher 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----- +# +# db: +# # The password to be used for authenticating database access. If this setting is omitted, a password will be +# # automatically generated upon initial deployment and the existing password will be used upon upgrades. +# password: +# value: +# +# # Internal "scanner-v4-db..svc" service TLS certificate for the Scanner V4 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----- diff --git a/rhacs/4.5.2/central-services/values-public.yaml.example b/rhacs/4.5.2/central-services/values-public.yaml.example new file mode 100644 index 0000000..cde5ecd --- /dev/null +++ b/rhacs/4.5.2/central-services/values-public.yaml.example @@ -0,0 +1,772 @@ +# 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 `quay.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 +# +# # Public configuration options for Scanner V4. +# scannerV4: +# +# # If this is set to false, Scanner V4 will be enabled and deployed. +# # Note that currently Scanner V4 cannot be used as the only scanner component. +# # Instead it must be currently deployed side-by-side with StackRox Scanner (scanner.disable=false). +# # If it is set to true, no other setting in this section will have any effect. +# disable: true +# +# # Scanner V4 consists of three components: indexer, matcher and db. +# +# # Configuration for the indexer component: +# indexer: +# # The log level for the indexer deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # 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-v4-indexer +# 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 +# +# # Default number of indexer replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 3 +# +# # Settings related to autoscaling the indexer deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any 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 indexer deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "3Gi" +# cpu: "2000m" +# +# # Configuration for the matcher component: +# matcher: +# # The log level for the matcher deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce matcher to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # 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-v4-matcher +# 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: DoesNotExists +# +# # Default number of matcher replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 2 +# +# # Settings related to autoscaling the matcher deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any 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: 3 +# +# # Resource settings for the matcher deployment. +# resources: +# requests: +# memory: "4Gi" +# cpu: "1000m" +# limits: +# memory: "5Gi" +# cpu: "2000m" +# +# # Configuration for the DB component: +# db: +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # Scanner V4 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 +# +# # Resource settings for the DB deployment. +# resources: +# requests: +# cpu: "200m" +# memory: "2Gi" +# limits: +# cpu: "2000m" +# memory: "4Gi" +# +# # Configure DB password. If `generate` is true, a new password will be +# # generated. If it is false, a valid password is expected in `value`. +# password: +# generate: null +# value: null +# +# # Configure persistence backend for the DB. +# persistence: +# persistentVolumeClaim: +# claimName: "scanner-v4-db" +# size: "50Gi" +# +# # 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.5.2/central-services/values.yaml b/rhacs/4.5.2/central-services/values.yaml new file mode 100644 index 0000000..3b71e34 --- /dev/null +++ b/rhacs/4.5.2/central-services/values.yaml @@ -0,0 +1,578 @@ +## 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: true + storage: + endpoint: "https://console.redhat.com/connections/api" + 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 +# +## Configuration options relating to Scanner V4. +#scannerV4: +# +# # If this is set to false, Scanner V4 will be enabled and deployed. +# # If it is set to true, no other setting in this section will have any effect. +# disable: true +# +# image: +# registry: null +# name: rhacs-scanner-v4-rhel8 +# tag: 4.5.2 +# fullRef: null +# +# indexer: +# # The log level for the indexer deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: null +# +# # If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: null +# +# # If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# podAntiAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 100 +# podAffinityTerm: +# labelSelector: +# matchLabels: +# app: scanner-v4-indexer +# 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 +# +# # Default number of indexer replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 3 +# +# # Settings related to autoscaling the indexer deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any effect. +# disable: false +# minReplicas: 2 +# maxReplicas: 5 +# +# # Resource settings for the indexer deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "3Gi" +# cpu: "2000m" +# +# # Settings for the internal service-to-service TLS certificate used by indexer. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# matcher: +# # The log level for the matcher deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce matcher to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: null +# +# # If the nodes selected by the node selector are tainted, you can specify the corresponding taint tolerations here. +# tolerations: null +# +# # If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# podAntiAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# - weight: 100 +# podAffinityTerm: +# labelSelector: +# matchLabels: +# app: scanner-v4-matcher +# 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 +# +# # Default number of matcher replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 2 +# # Settings related to autoscaling the matcher deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any effect. +# disable: false +# minReplicas: 2 +# maxReplicas: 3 +# +# # Resource settings for the matcher deployment. +# resources: +# requests: +# memory: "4Gi" +# cpu: "1000m" +# limits: +# memory: "5Gi" +# cpu: "2000m" +# +# # Settings for the internal service-to-service TLS certificate used by matcher. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# db: +# image: +# registry: null +# name: rhacs-scanner-v4-db-rhel8 +# tag: 4.5.2 +# fullRef: null +# +# # Resource settings for the DB deployment. +# resources: +# requests: +# cpu: "200m" +# memory: "2Gi" +# limits: +# cpu: "2000m" +# memory: "4Gi" +# +# # Configure DB password. If `generate` is true, a new password will be +# # generated. If it is false, a valid password is expected in `value`. +# password: +# generate: null +# value: null +# +# # Configure persistence backend for the DB. +# # By default a PVC is used. Unless a Storage Class is specified +# # a default Storage Class is expected. +# persistence: +# hostPath: null +# persistentVolumeClaim: +# claimName: "scanner-v4-db" +# size: "50Gi" +# createClaim: true +# storageClass: null +# none: null +# +# nodeSelector: null +# +# # Settings for the internal service-to-service TLS certificate used by the DB. +# # See the documentation for `ca` at the top level for an explanation. +# serviceTLS: +# cert: null +# key: null +# generate: null +# +# postgresConfig: "@config-templates/scanner-v4-db/postgresql.conf|config-templates/scanner-v4-db/postgresql.conf.default" +# hbaConfig: "@config-templates/scanner-v4-db/pg_hba.conf|config-templates/scanner-v4-db/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 +# +# +## 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.5.2/secured-cluster-services/.helmignore b/rhacs/4.5.2/secured-cluster-services/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/Chart.yaml b/rhacs/4.5.2/secured-cluster-services/Chart.yaml new file mode 100644 index 0000000..0c6b643 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/Chart.yaml @@ -0,0 +1,8 @@ +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.5.2 +appVersion: 4.5.2 diff --git a/rhacs/4.5.2/secured-cluster-services/README.md b/rhacs/4.5.2/secured-cluster-services/README.md new file mode 100644 index 0000000..ae32905 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/README.md @@ -0,0 +1,474 @@ +# 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. Optionally StackRox Scanner can be deployed, either alone or together +with the new Scanner V4. + +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 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 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 + ``` + +#### 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. + +Furthermore, the files `values-scanner.yaml.example`, `values-public-scanner-v4.yaml.example` +and `values-private-scanner-v4.yaml.example` list the most commonly used configuration options +for StackRox Scanner and Scanner V4. + +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. Must be a dictionary where both keys and values are strings. | `{}` | +|`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.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.forceCollectionMethod`|Deprecated. This value has no effect. |`false` | +|`collector.collectionMethod`|Either `CORE_BPF`, or `NO_COLLECTION`. |`CORE_BPF` | +|`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`| Deprecated. Slim and regular Collector images are identical.|`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) | +|`collector.priorityClassName` | Name of a cluster's PriorityClass object to assign to Collector pods. | `null` (no PriorityClass assignment) | +|`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. | `true` | +|`scannerV4.disable`| Enable Scanner V4. StackRox Scanner must be enabled as well (`scanner.disable=false``). | `true` | +### Default resources + +Each of the baseline container's default resource settings are defined in the +`internal/defaults/40-resources.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/40-resources.yaml` | +|:----------------|:---------------------------------------------| +|Sensor |`sensor.resources` | +|Collector |`collector.resources` | +|Compliance |`collector.complianceResources` | +|NodeInventory |`collector.nodeScanningResources` | +|Admission Control|`admissionControl.resources` | + +Furthermore, default resource settings for StackRox Scanner and Scanner V4 can be +found in the files `internal/defaults/70-scanner.yaml` and `internal/defaults/70-scanner-v4.yaml`. + +### 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.5.2/secured-cluster-services/assets/Red_Hat-Hat_icon.png b/rhacs/4.5.2/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.5.2/secured-cluster-services/assets/StackRox_icon.png b/rhacs/4.5.2/secured-cluster-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.5.2/secured-cluster-services/config-templates/scanner-v4-db/pg_hba.conf.default b/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/pg_hba.conf.default new file mode 100644 index 0000000..650f2fe --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/pg_hba.conf.default @@ -0,0 +1,23 @@ +# 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 reject +host replication all 127.0.0.1/32 reject +host replication all ::1/128 reject + +### 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.5.2/secured-cluster-services/config-templates/scanner-v4-db/postgresql.conf.default b/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/postgresql.conf.default new file mode 100644 index 0000000..63ed892 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4-db/postgresql.conf.default @@ -0,0 +1,75 @@ +#------------------------------------------------------------------------------ +# FILE LOCATIONS +#------------------------------------------------------------------------------ + +hba_file = '/etc/stackrox.d/config/pg_hba.conf' + +#------------------------------------------------------------------------------ +# CONNECTIONS AND AUTHENTICATION +#------------------------------------------------------------------------------ + +# - Connection Settings - + +listen_addresses = '*' +max_connections = 500 + +# - Authentication - + +password_encryption = 'scram-sha-256' + +# - SSL - + +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' + +#------------------------------------------------------------------------------ +# RESOURCE USAGE (except WAL) +#------------------------------------------------------------------------------ + +# - Memory - + +# Keep this in sync with the shared-memory volume in the +# templates/02-scanner-v4-07-db-deployment.yaml +shared_buffers = 750MB +work_mem = 16MB +maintenance_work_mem = 128MB +dynamic_shared_memory_type = posix + +#------------------------------------------------------------------------------ +# WRITE-AHEAD LOG +#------------------------------------------------------------------------------ + +# - Checkpoints - + +max_wal_size = 3GB +min_wal_size = 80MB + +#------------------------------------------------------------------------------ +# REPORTING AND LOGGING +#------------------------------------------------------------------------------ + +# - What to Log - + +log_timezone = 'Etc/UTC' + +#------------------------------------------------------------------------------ +# CLIENT CONNECTION DEFAULTS +#------------------------------------------------------------------------------ + +# - Locale and Formatting - + +datestyle = 'iso, mdy' +timezone = 'Etc/UTC' + +lc_messages = 'en_US.utf8' +lc_monetary = 'en_US.utf8' +lc_numeric = 'en_US.utf8' +lc_time = 'en_US.utf8' + +default_text_search_config = 'pg_catalog.english' + +# - Shared Library Preloading - + +shared_preload_libraries = 'pg_stat_statements' diff --git a/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4/indexer-config.yaml.tpl b/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4/indexer-config.yaml.tpl new file mode 100644 index 0000000..c5d28fc --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4/indexer-config.yaml.tpl @@ -0,0 +1,47 @@ +{{- /* + This is the configuration file template for the Scanner v4 Indexer. + 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 v4 Indexer. +stackrox_services: true +indexer: + enable: true + database: + conn_string: > + host=scanner-v4-db.{{ .Release.Namespace }}.svc + port=5432 + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + user=postgres + sslmode=verify-full +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.statementTimeoutMs) }} + statement_timeout={{._rox.scannerV4.db.source.statementTimeoutMs}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.minConns) }} + pool_min_conns={{._rox.scannerV4.db.source.minConns}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.maxConns) }} + pool_max_conns={{._rox.scannerV4.db.source.maxConns}} +{{- end }} + client_encoding=UTF8 + password_file: /run/secrets/stackrox.io/secrets/password + get_layer_timeout: 1m + {{- if ._rox.env.centralServices }} + repository_to_cpe_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?file=repo2cpe + name_to_repos_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?file=name2repos + {{- else }} + repository_to_cpe_url: https://sensor.{{ .Release.Namespace }}.svc/scanner/definitions?file=repo2cpe + name_to_repos_url: https://sensor.{{ .Release.Namespace }}.svc/scanner/definitions?file=name2repos + {{- end }} + repository_to_cpe_file: /run/mappings/repository-to-cpe.json + name_to_repos_file: /run/mappings/container-name-repos-map.json +matcher: + enable: false +log_level: "{{ ._rox.scannerV4.indexer.logLevel }}" +grpc_listen_addr: 0.0.0.0:8443 +http_listen_addr: 0.0.0.0:9443 +proxy: + config_dir: /run/secrets/stackrox.io/proxy-config + config_file: config.yaml diff --git a/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4/matcher-config.yaml.tpl b/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4/matcher-config.yaml.tpl new file mode 100644 index 0000000..4414553 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/config-templates/scanner-v4/matcher-config.yaml.tpl @@ -0,0 +1,39 @@ +{{- /* + This is the configuration file template for the Scanner v4 Matcher. + 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 v4 Matcher. +stackrox_services: true +indexer: + enable: false +matcher: + enable: true + database: + conn_string: > + host=scanner-v4-db.{{ .Release.Namespace }}.svc + port=5432 + sslrootcert=/run/secrets/stackrox.io/certs/ca.pem + user=postgres + sslmode=verify-full +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.statementTimeoutMs) }} + statement_timeout={{._rox.scannerV4.db.source.statementTimeoutMs}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.minConns) }} + pool_min_conns={{._rox.scannerV4.db.source.minConns}} +{{- end }} +{{- if not (kindIs "invalid" ._rox.scannerV4.db.source.maxConns) }} + pool_max_conns={{._rox.scannerV4.db.source.maxConns}} +{{- end }} + client_encoding=UTF8 + password_file: /run/secrets/stackrox.io/secrets/password + vulnerabilities_url: https://central.{{ .Release.Namespace }}.svc/api/extensions/scannerdefinitions?version=ROX_VERSION + indexer_addr: scanner-v4-indexer.{{ .Release.Namespace }}.svc:8443 +log_level: "{{ ._rox.scannerV4.matcher.logLevel }}" +grpc_listen_addr: 0.0.0.0:8443 +http_listen_addr: 0.0.0.0:9443 +proxy: + config_dir: /run/secrets/stackrox.io/proxy-config + config_file: config.yaml diff --git a/rhacs/4.5.2/secured-cluster-services/config-templates/scanner/config.yaml.tpl b/rhacs/4.5.2/secured-cluster-services/config-templates/scanner/config.yaml.tpl new file mode 100644 index 0000000..5efc0b9 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/internal/annotations/helm-hook_secret.yaml b/rhacs/4.5.2/secured-cluster-services/internal/annotations/helm-hook_secret.yaml new file mode 100644 index 0000000..68eea0c --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/internal/annotations/helm-hook_secret.yaml @@ -0,0 +1,2 @@ +helm.sh/hook: pre-install,pre-upgrade +helm.sh/resource-policy: keep diff --git a/rhacs/4.5.2/secured-cluster-services/internal/annotations/helm-hook_storage.yaml b/rhacs/4.5.2/secured-cluster-services/internal/annotations/helm-hook_storage.yaml new file mode 100644 index 0000000..7376533 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/internal/annotations/helm-hook_storage.yaml @@ -0,0 +1,3 @@ +helm.sh/hook: pre-install,pre-upgrade +helm.sh/resource-policy: keep +helm.sh/hook-delete-policy: never diff --git a/rhacs/4.5.2/secured-cluster-services/internal/cluster-config.yaml.tpl b/rhacs/4.5.2/secured-cluster-services/internal/cluster-config.yaml.tpl new file mode 100644 index 0000000..a85ddd7 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/internal/compatibility-translation.yaml b/rhacs/4.5.2/secured-cluster-services/internal/compatibility-translation.yaml new file mode 100644 index 0000000..4e33afc --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/internal/config-shape.yaml b/rhacs/4.5.2/secured-cluster-services/internal/config-shape.yaml new file mode 100644 index 0000000..4a29271 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/internal/config-shape.yaml @@ -0,0 +1,198 @@ +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 + scannerV4: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string +env: + openshift: null # bool | int + istio: null # bool + storageClasses: + all: {} # dict + default: null # string + pvcs: + names: null # [string] +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] + hostAliases: null # [dict] + priorityClassName: null # string + 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] + hostAliases: null # [dict] + priorityClassName: null # string +collector: + forceCollectionMethod: null # bool + 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 + priorityClassName: null # string + hostAliases: null # [dict] + disableSELinuxOptions: null # bool + seLinuxOptionsType: null # string + containerd: + enabled: null # bool + crio: + enabled: null # bool + runtime_config: + enabled: null # bool +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 + scanner-v4-indexer: + labels: {} # dict + annotations: {} # dict + podLabels: {} # dict + podAnnotations: {} # dict + envVars: {} # dict + scanner-v4-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: + namespaceOverride: null # bool + useLookup: null # bool + fileOverrides: {} # dict + configFingerprintOverride: null # string + apiServer: + version: null # string + overrideAPIResources: null # [string] + extraAPIResources: null # [string] +network: + enableNetworkPolicies: null # bool +system: + enablePodSecurityPolicies: null # bool diff --git a/rhacs/4.5.2/secured-cluster-services/internal/defaults/00-bootstrap.yaml b/rhacs/4.5.2/secured-cluster-services/internal/defaults/00-bootstrap.yaml new file mode 100644 index 0000000..846ca57 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/internal/defaults/10-env.yaml b/rhacs/4.5.2/secured-cluster-services/internal/defaults/10-env.yaml new file mode 100644 index 0000000..48605ae --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/internal/defaults/20-tls-files.yaml b/rhacs/4.5.2/secured-cluster-services/internal/defaults/20-tls-files.yaml new file mode 100644 index 0000000..6eb6408 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/internal/defaults/30-base-config.yaml b/rhacs/4.5.2/secured-cluster-services/internal/defaults/30-base-config.yaml new file mode 100644 index 0000000..4919efe --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/internal/defaults/30-base-config.yaml @@ -0,0 +1,120 @@ +# 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: 10 + 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: "CORE_BPF" + disableTaintTolerations: false + nodescanningEndpoint: "127.0.0.1:8444" + tolerations: + - operator: "Exists" + +auditLogs: + disableCollection: {{ ne ._rox.env.openshift 4 }} + +network: + enableNetworkPolicies: true + +enableOpenShiftMonitoring: false +--- +sensor: + exposeMonitoring: {{ ._rox.exposeMonitoring }} +collector: + exposeMonitoring: {{ ._rox.exposeMonitoring }} +admissionControl: + exposeMonitoring: {{ ._rox.exposeMonitoring }} diff --git a/rhacs/4.5.2/secured-cluster-services/internal/defaults/40-resources.yaml b/rhacs/4.5.2/secured-cluster-services/internal/defaults/40-resources.yaml new file mode 100644 index 0000000..4dd0c19 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/internal/defaults/50-images.yaml b/rhacs/4.5.2/secured-cluster-services/internal/defaults/50-images.yaml new file mode 100644 index 0000000..7e21ca7 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/internal/defaults/50-images.yaml @@ -0,0 +1,124 @@ +# 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.5.2 + scannerDb: + name: rhacs-scanner-db-slim-rhel8 + tag: 4.5.2 + scannerV4: + name: rhacs-scanner-v4-rhel8 + tag: 4.5.2 + scannerV4DB: + name: rhacs-scanner-v4-db-rhel8 + tag: 4.5.2 +--- +# 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 }} + scannerV4: + registry: {{ ._rox.image.registry }} + scannerV4DB: + 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 "/" }} + scannerV4: + repository: {{ list ._rox.image.scannerV4.registry ._rox.image.scannerV4.name | compact | join "/" }} + scannerV4DB: + repository: {{ list ._rox.image.scannerV4DB.registry ._rox.image.scannerV4DB.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.5.2 + 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.5.2" + pullPolicy: IfNotPresent + {{- else }} + tag: "4.5.2" + 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 }}" + scannerV4: + fullRef: "{{ printf "%s:%s" ._rox.image.scannerV4.repository ._rox.image.scannerV4.tag }}" + scannerV4DB: + fullRef: "{{ printf "%s:%s" ._rox.image.scannerV4DB.repository ._rox.image.scannerV4DB.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.5.2/secured-cluster-services/internal/defaults/70-scanner-v4.yaml b/rhacs/4.5.2/secured-cluster-services/internal/defaults/70-scanner-v4.yaml new file mode 100644 index 0000000..afbf0a9 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/internal/defaults/70-scanner-v4.yaml @@ -0,0 +1,105 @@ + +scannerV4: + + disable: true + indexer: + disable: false + replicas: 2 + logLevel: INFO + metricsPort: 9090 + autoscaling: + disable: false + minReplicas: 2 + maxReplicas: 5 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: + app: scanner-v4-indexer + 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: "3Gi" + cpu: "2000m" + db: + postgresConfig: "@config-templates/scanner-v4-db/postgresql.conf|config-templates/scanner-v4-db/postgresql.conf.default" + hbaConfig: "@config-templates/scanner-v4-db/pg_hba.conf|config-templates/scanner-v4-db/pg_hba.conf.default" + source: + minConns: 10 + maxConns: 80 + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # Scanner V4 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 + resources: + requests: + cpu: "200m" + memory: "2Gi" + limits: + cpu: "2000m" + memory: "4Gi" + exposeMonitoring: {{ ._rox.exposeMonitoring }} + +scannerV4DBPVCDefaults: + claimName: "scanner-v4-db" + size: "10Gi" + createClaim: true diff --git a/rhacs/4.5.2/secured-cluster-services/internal/defaults/70-scanner.yaml b/rhacs/4.5.2/secured-cluster-services/internal/defaults/70-scanner.yaml new file mode 100644 index 0000000..2d4d5f4 --- /dev/null +++ b/rhacs/4.5.2/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: "512Mi" + + slimImage: + name: "" + tag: "" + fullRef: "" + repository: "" + + slimDBImage: + name: "" + tag: "" + fullRef: "" + repository: "" diff --git a/rhacs/4.5.2/secured-cluster-services/internal/defaults/whats-this.md b/rhacs/4.5.2/secured-cluster-services/internal/defaults/whats-this.md new file mode 100644 index 0000000..d58c8de --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/internal/expandables.yaml b/rhacs/4.5.2/secured-cluster-services/internal/expandables.yaml new file mode 100644 index 0000000..fc280fc --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/internal/expandables.yaml @@ -0,0 +1,61 @@ +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 +scannerV4: + indexer: + nodeSelector: true + resources: true + serviceTLS: + cert: true + key: true + db: + postgresConfig: true + hbaConfig: true + password: + value: true + nodeSelector: true + resources: true + serviceTLS: + cert: true + key: true diff --git a/rhacs/4.5.2/secured-cluster-services/internal/scanner-config-shape.yaml b/rhacs/4.5.2/secured-cluster-services/internal/scanner-config-shape.yaml new file mode 100644 index 0000000..1a5d26f --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/internal/scanner-config-shape.yaml @@ -0,0 +1,44 @@ +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] + hostAliases: null # [dict] + dbHostAliases: null # [dict] + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + affinity: null # dict + priorityClassName: null # string + dbPriorityClassName: null # string + 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.5.2/secured-cluster-services/internal/scanner-v4-config-shape.yaml b/rhacs/4.5.2/secured-cluster-services/internal/scanner-v4-config-shape.yaml new file mode 100644 index 0000000..a705b53 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/internal/scanner-v4-config-shape.yaml @@ -0,0 +1,79 @@ +scannerV4: + disable: null # bool + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + indexer: + disable: null # bool + metricsPort: null # int + logLevel: null # string + replicas: null # int + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + matcher: + metricsPort: null # int + logLevel: null # string + replicas: null # int + autoscaling: + disable: null # bool + minReplicas: null # int + maxReplicas: null # int + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + db: + image: + registry: null # string + name: null # string + tag: null # string + fullRef: null # string + source: + minConns: null # int + maxConns: null # int + statementTimeoutMs: null # int + configOverride: null # string + password: + value: null # string + generate: null # bool + nodeSelector: null # string | dict + tolerations: null # [dict] + affinity: null # dict + hostAliases: null # [dict] + resources: null # string | dict + serviceTLS: + cert: null # string + key: null # string + generate: null # bool + postgresConfig: null # string + hbaConfig: null # string + 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] + exposeMonitoring: null # bool diff --git a/rhacs/4.5.2/secured-cluster-services/scripts/fetch-secrets.sh b/rhacs/4.5.2/secured-cluster-services/scripts/fetch-secrets.sh new file mode 100755 index 0000000..850a227 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl b/rhacs/4.5.2/secured-cluster-services/scripts/fetched-secrets-bundle-ca-only.yaml.tpl new file mode 100644 index 0000000..b5a13c2 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl b/rhacs/4.5.2/secured-cluster-services/scripts/fetched-secrets-bundle.yaml.tpl new file mode 100644 index 0000000..72bb452 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/sensor-chart-upgrade.md b/rhacs/4.5.2/secured-cluster-services/sensor-chart-upgrade.md new file mode 100644 index 0000000..615a03a --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml b/rhacs/4.5.2/secured-cluster-services/templates/00-collector-image-pull-secrets.yaml new file mode 100644 index 0000000..596b54a --- /dev/null +++ b/rhacs/4.5.2/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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_secret" $annotations) -}} + {{- include "srox.annotations" (list . "secret" "secured-cluster-services-collector" $annotations) | nindent 4 }} +data: + .dockerconfigjson: {{ dict "auths" ._rox.collectorImagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/00-injected-ca-bundle.yaml b/rhacs/4.5.2/secured-cluster-services/templates/00-injected-ca-bundle.yaml new file mode 100644 index 0000000..3289c2a --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/00-main-image-pull-secrets.yaml b/rhacs/4.5.2/secured-cluster-services/templates/00-main-image-pull-secrets.yaml new file mode 100644 index 0000000..c033f7d --- /dev/null +++ b/rhacs/4.5.2/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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_secret" $annotations) -}} + {{- include "srox.annotations" (list . "secret" "secured-cluster-services-main" $annotations) | nindent 4 }} +data: + .dockerconfigjson: {{ dict "auths" ._rox.mainImagePullSecrets._dockerAuths | toJson | b64enc | quote }} +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/00-storage-class.yaml b/rhacs/4.5.2/secured-cluster-services/templates/00-storage-class.yaml new file mode 100644 index 0000000..ed5c3a0 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/00-storage-class.yaml @@ -0,0 +1,26 @@ +{{- include "srox.init" . -}} + + +{{- $name := "stackrox-gke-ssd" -}} +{{- if has $name ._rox._state.referencedStorageClasses }} + {{- $lookupOut := dict -}} + {{- $globalName := include "srox.globalResourceName" (list . $name) -}} + {{- $_ := include "srox.safeLookup" (list . $lookupOut "storage.k8s.io/v1" "StorageClass" "" $globalName) -}} + {{- if and (not $lookupOut.result) (or .Release.IsInstall $lookupOut.reliable) (not ._rox.meta.noCreateStorageClass) }} + +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ $globalName }} + labels: + {{- include "srox.labels" (list . "storageclass" $name) | nindent 4 }} + annotations: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_storage" $annotations) -}} + {{- include "srox.annotations" (list . "storageclass" $name $annotations) | nindent 4 }} +provisioner: kubernetes.io/gce-pd +parameters: + type: pd-ssd + + {{- end }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-00-serviceaccount.yaml new file mode 100644 index 0000000..a27c602 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-01-psps.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-01-psps.yaml new file mode 100644 index 0000000..23b398c --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-01-security.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-01-security.yaml new file mode 100644 index 0000000..05ff6f1 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-01-security.yaml @@ -0,0 +1,45 @@ +{{- include "srox.init" . -}} + +{{- if not ._rox.scanner.disable }} + +{{- if ._rox.env.openshift }} +--- +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: + - nonroot-v2 + 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.5.2/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-02-db-password-secret.yaml new file mode 100644 index 0000000..c6c0bc1 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-04-scanner-config.yaml new file mode 100644 index 0000000..4ed16c7 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-05-network-policy.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-05-network-policy.yaml new file mode 100644 index 0000000..a61b59e --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-05-network-policy.yaml @@ -0,0 +1,91 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies -}} +{{- 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 + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8080 + protocol: TCP + - port: 8443 + protocol: TCP + 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 }} +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-06-deployment.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-06-deployment.yaml new file mode 100644 index 0000000..6bbe53c --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-06-deployment.yaml @@ -0,0 +1,318 @@ +{{- 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scanner._nodeSelector }} + nodeSelector: + {{- ._rox.scanner._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.tolerations }} + tolerations: + {{- toYaml ._rox.scanner.tolerations | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.hostAliases }} + hostAliases: {{ toYaml ._rox.scanner.hostAliases | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scanner.affinity | nindent 8 }} + {{- if ._rox.scanner.priorityClassName }} + priorityClassName: {{ ._rox.scanner.priorityClassName }} + {{- end }} + 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: ROX_MEMLIMIT + 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 + {{- if eq ._rox.scanner.mode "slim" }} + secretName: additional-ca-sensor + {{- else }} + secretName: additional-ca + {{- end }} + - 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scanner._dbNodeSelector }} + nodeSelector: + {{- ._rox.scanner._dbNodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scanner.dbHostAliases }} + hostAliases: {{ toYaml ._rox.scanner.dbHostAliases | 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 + {{- if ._rox.scanner.dbPriorityClassName }} + priorityClassName: {{ ._rox.scanner.dbPriorityClassName }} + {{- end }} + 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.5.2/secured-cluster-services/templates/02-scanner-07-service.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-07-service.yaml new file mode 100644 index 0000000..2f65b15 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-08-hpa.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-08-hpa.yaml new file mode 100644 index 0000000..c7af476 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/02-scanner-v4-00-serviceaccount.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-00-serviceaccount.yaml new file mode 100644 index 0000000..91e4c8e --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-00-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- include "srox.init" . -}} +{{- if (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: scanner-v4 + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "serviceaccount" "scanner-v4") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "serviceaccount" "scanner-v4") | nindent 4 }} +imagePullSecrets: +{{- range $secretName := ._rox.imagePullSecrets._names }} +- name: {{ quote $secretName }} +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-psps.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-psps.yaml new file mode 100644 index 0000000..14e38b4 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-psps.yaml @@ -0,0 +1,72 @@ +{{- include "srox.init" . -}} +{{- if and (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) ._rox.system.enablePodSecurityPolicies }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4-psp") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox-scanner-v4-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox-scanner-v4-psp") | nindent 4 }} +rules: +- apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4") }} + verbs: + - use + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stackrox-scanner-v4-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "stackrox-scanner-v4-psp") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "stackrox-scanner-v4-psp") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4-psp") }} +subjects: +- kind: ServiceAccount + name: scanner-v4 + namespace: {{ .Release.Namespace }} + +--- + +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox-scanner-v4") }} + labels: + {{- include "srox.labels" (list . "podsecuritypolicy" "stackrox-scanner-v4") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "podsecuritypolicy" "stackrox-scanner-v4") | 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.5.2/secured-cluster-services/templates/02-scanner-v4-01-security.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-security.yaml new file mode 100644 index 0000000..d76329c --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-01-security.yaml @@ -0,0 +1,51 @@ +{{- include "srox.init" . -}} + +{{- if or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled }} + {{- if ._rox.env.openshift }} + {{- if eq ._rox.env.openshift 3 }} + {{ include "srox.warn" (list . "On OpenShift 3.x no SecurityContextConstraint will be configured for Scanner V4.") }} + {{- else }} + {{/* Use a default SCC that ships with OpenShift 4.x. + We only need to create a Role and a RoleBinding for + associating the SCC with the Scanner V4 deployment. */}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: use-scanner-v4-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "role" "use-scanner-v4-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "role" "use-scanner-v4-scc") | nindent 4 }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - nonroot-v2 + verbs: + - use + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: scanner-v4-use-scc + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "rolebinding" "scanner-v4-use-scc") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" "scanner-v4-use-scc") | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: use-scanner-v4-scc +subjects: +- kind: ServiceAccount + name: scanner-v4 + namespace: {{ .Release.Namespace }} + {{- end }} + {{- end }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-02-db-password-secret.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-02-db-password-secret.yaml new file mode 100644 index 0000000..a382d3e --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-02-db-password-secret.yaml @@ -0,0 +1,19 @@ +{{- include "srox.init" . -}} +{{- /* The (...) below safe-guard against nil pointer evaluations for Helm versions built with Go < 1.18. */}} +{{- if and ._rox.scannerV4._dbEnabled (not (kindIs "invalid" (._rox.scannerV4.db._password).value)) }} +apiVersion: v1 +kind: Secret +metadata: + name: scanner-v4-db-password + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "secret" "scanner-v4-db-password") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "secret" "scanner-v4-db-password") | nindent 4 }} + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/resource-policy": keep +type: Opaque +stringData: + password: | + {{- ._rox.scannerV4.db._password.value | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-db-config.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-db-config.yaml new file mode 100644 index 0000000..439cfe8 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-db-config.yaml @@ -0,0 +1,17 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-db-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-db-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-db-config") | nindent 4 }} +data: + postgresql.conf: | + {{- ._rox.scannerV4.db._postgresConfig | nindent 4 }} + pg_hba.conf: | + {{- ._rox.scannerV4.db._hbaConfig | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-indexer-config.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-indexer-config.yaml new file mode 100644 index 0000000..26705b8 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-04-indexer-config.yaml @@ -0,0 +1,15 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: scanner-v4-indexer-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "configmap" "scanner-v4-indexer-config") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "configmap" "scanner-v4-indexer-config") | nindent 4 }} +data: + config.yaml: | + {{- tpl (.Files.Get "config-templates/scanner-v4/indexer-config.yaml.tpl") . | nindent 4 }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-db-network-policy.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-db-network-policy.yaml new file mode 100644 index 0000000..875aba8 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-db-network-policy.yaml @@ -0,0 +1,39 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-db") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-db + ingress: +{{- if ._rox.scannerV4._indexerEnabled }} + - from: + - podSelector: + matchLabels: + app: scanner-v4-indexer + ports: + - port: 5432 + protocol: TCP +{{- end }} +{{- if ._rox.scannerV4._matcherEnabled }} + - from: + - podSelector: + matchLabels: + app: scanner-v4-matcher + ports: + - port: 5432 + protocol: TCP + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-indexer-network-policy.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-indexer-network-policy.yaml new file mode 100644 index 0000000..460801a --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-05-indexer-network-policy.yaml @@ -0,0 +1,90 @@ +{{- include "srox.init" . -}} +{{- if ._rox.network.enableNetworkPolicies }} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer") | nindent 4 }} +spec: + podSelector: + matchLabels: + app: scanner-v4-indexer + ingress: + {{- if ._rox.env.centralServices }} + - from: + - podSelector: + matchLabels: + app: central + ports: + - port: 8443 + protocol: TCP + - from: + - podSelector: + matchLabels: + app: scanner-v4-matcher + ports: + - port: 8443 + protocol: TCP + {{- end }} + - from: + - podSelector: + matchLabels: + app: sensor + ports: + - port: 8443 + protocol: TCP + policyTypes: + - Ingress + +{{- if ._rox.scannerV4.exposeMonitoring }} +--- + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer-monitoring") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer-monitoring") | nindent 4 }} +spec: + ingress: + - ports: + - port: {{ ._rox.scannerV4.indexer.metricsPort }} + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-indexer + policyTypes: + - Ingress +{{- end }} +{{- if ._rox.monitoring.openshift.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: scanner-v4-indexer-monitoring-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "networkpolicy" "scanner-v4-indexer-monitoring-tls") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "networkpolicy" "scanner-v4-indexer-monitoring-tls") | nindent 4 }} +spec: + ingress: + - ports: + - port: 9091 + protocol: TCP + podSelector: + matchLabels: + app: scanner-v4-indexer + policyTypes: + - Ingress +{{- end }} +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-06-db-pvc.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-06-db-pvc.yaml new file mode 100644 index 0000000..8b27634 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-06-db-pvc.yaml @@ -0,0 +1,66 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.scannerV4._dbEnabled }} + +{{- if ._rox.scannerV4.db.persistence._pvcCfg }} +{{- $pvcCfg := ._rox.scannerV4.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 }} +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: + # this is used for backwards compatibility for operator if there are PVCs without annotation + # owned by the operator it will assume they belong to the deprecated central-db + {{- $labels := dict "target.pvc.stackrox.io" "scanner-v4-db" -}} + {{- include "srox.labels" (list . "persistentvolumeclaim" "scanner-v4-db" $labels) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "persistentvolumeclaim" "scanner-v4-db") | nindent 4 }} +spec: + {{- if $storageClassName }} + storageClassName: {{ $storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ include "srox.formatStorageSize" $pvcCfg.size }} +{{- end }} + +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-db-deployment.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-db-deployment.yaml new file mode 100644 index 0000000..953cb1c --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-db-deployment.yaml @@ -0,0 +1,142 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-db + {{- include "srox.labels" (list . "deployment" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-db") | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-db + strategy: + type: Recreate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-db + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-db") | nindent 8 }} + annotations: + traffic.sidecar.istio.io/excludeInboundPorts: "5432" + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-db") | nindent 8 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: nonroot-v2 + {{- end }} + spec: + {{- if ._rox.scannerV4.db._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.db._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.db.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.db.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.db.affinity | nindent 8 }} + {{- if ._rox.scannerV4.db.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.db.hostAliases | nindent 8 }} + {{- end }} + serviceAccountName: scanner-v4 + terminationGracePeriodSeconds: 120 + initContainers: + - name: init-db + image: {{ ._rox.scannerV4.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + - name: POSTGRES_HOST_AUTH_METHOD + value: "scram-sha-256" + - name: POSTGRES_PASSWORD_FILE + value: "/run/secrets/stackrox.io/secrets/password" +{{- if ._rox.env.centralServices }} + - name: SCANNER_DB_INIT_BUNDLE_ENABLED + value: "true" +{{- end }} + command: + - init-entrypoint.sh + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: scanner-v4-db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + resources: + {{- ._rox.scannerV4.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + containers: + - name: db + image: {{ ._rox.scannerV4.db.image.fullRef | quote }} + env: + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + - name: POSTGRES_HOST_AUTH_METHOD + value: "scram-sha-256" + {{- include "srox.envVars" (list . "deployment" "scanner-v4-db" "db") | nindent 8 }} + ports: + - name: tcp-postgresql + containerPort: 5432 + 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.scannerV4.db._resources | nindent 10 }} + securityContext: + runAsUser: 70 + runAsGroup: 70 + volumeMounts: + - name: disk + mountPath: /var/lib/postgresql/data + - name: config-volume + mountPath: /etc/stackrox.d/config/ + - name: scanner-db-tls-volume + mountPath: /run/secrets/stackrox.io/certs + - name: shared-memory + mountPath: /dev/shm + securityContext: + fsGroup: 70 + volumes: + - name: disk + {{- toYaml ._rox.scannerV4.db.persistence._volumeCfg | nindent 8 }} + - name: config-volume + configMap: + name: {{ default "scanner-v4-db-config" ._rox.scannerV4.db.configOverride }} + - name: scanner-db-tls-volume + secret: + secretName: scanner-v4-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-templates/scanner-v4-db/postgresql.conf.default */}} + sizeLimit: 750Mi + - name: scanner-v4-db-password + secret: + secretName: scanner-v4-db-password +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-indexer-deployment.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-indexer-deployment.yaml new file mode 100644 index 0000000..2be0860 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-07-indexer-deployment.yaml @@ -0,0 +1,174 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-indexer + {{- include "srox.labels" (list . "deployment" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "deployment" "scanner-v4-indexer") | nindent 4 }} +spec: + replicas: {{ ._rox.scannerV4.indexer.replicas }} + minReadySeconds: 15 + selector: + matchLabels: + app: scanner-v4-indexer + strategy: + type: RollingUpdate + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app: scanner-v4-indexer + {{- include "srox.podLabels" (list . "deployment" "scanner-v4-indexer") | nindent 8 }} + annotations: + {{- $annotations := dict "traffic.sidecar.istio.io/excludeInboundPorts" "8443" -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "nonroot-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "scanner-v4-indexer" $annotations) | nindent 8 }} + spec: + {{- if ._rox.scannerV4.indexer._nodeSelector }} + nodeSelector: + {{- ._rox.scannerV4.indexer._nodeSelector | nindent 8 }} + {{- end }} + {{- if ._rox.scannerV4.indexer.tolerations }} + tolerations: + {{- toYaml ._rox.scannerV4.indexer.tolerations | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.scannerV4.indexer.affinity | nindent 8 }} + {{- if ._rox.scannerV4.indexer.hostAliases }} + hostAliases: {{ toYaml ._rox.scannerV4.indexer.hostAliases | nindent 8 }} + {{- end }} + containers: + - name: indexer + image: {{ ._rox.scannerV4.indexer.image.fullRef | quote }} + env: + - name: ROX_MEMLIMIT + 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 }} + - name: ROX_METRICS_PORT + value: ":{{- ._rox.scannerV4.indexer.metricsPort -}}" + {{- if ._rox.monitoring.openshift.enabled }} + - name: ROX_ENABLE_SECURE_METRICS + value: "true" + - name: ROX_SECURE_METRICS_PORT + value: ":9091" + {{- end }} + {{- include "srox.envVars" (list . "deployment" "scanner-v4-indexer" "indexer") | nindent 8 }} + resources: + {{- ._rox.scannerV4.indexer._resources | nindent 10 }} + command: + - entrypoint.sh + - --conf=/etc/scanner/config.yaml + ports: + - name: grpc + containerPort: 8443 + {{ if ._rox.scannerV4.exposeMonitoring -}} + - name: monitoring + containerPort: {{ ._rox.scannerV4.indexer.metricsPort }} + {{- end}} + {{- if ._rox.monitoring.openshift.enabled }} + - containerPort: 9091 + name: monitoring-tls + {{- end }} + securityContext: + capabilities: + drop: ["NET_RAW"] + runAsNonRoot: true + runAsUser: 65534 + readinessProbe: + httpGet: + scheme: HTTPS + path: /health/readiness + port: 9443 + periodSeconds: 5 + timeoutSeconds: 1 + volumeMounts: + - name: additional-ca-volume + mountPath: /usr/local/share/ca-certificates/ + readOnly: true + - name: etc-ssl-volume + mountPath: /etc/ssl + - name: etc-pki-volume + mountPath: /etc/pki/ca-trust + - name: tls-volume + mountPath: /run/secrets/stackrox.io/certs/ + readOnly: true + - name: config-volume + mountPath: /etc/scanner + readOnly: true + - name: proxy-config-volume + mountPath: /run/secrets/stackrox.io/proxy-config/ + readOnly: true + - name: tmp-volume + mountPath: /tmp + - name: db-password + mountPath: /run/secrets/stackrox.io/secrets + readOnly: true + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + mountPath: /run/secrets/stackrox.io/monitoring-tls + readOnly: true + {{- end }} + {{- include "srox.injectedCABundleVolumeMount" . | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: scanner-v4 + volumes: + - name: additional-ca-volume + secret: + optional: true + {{- if ._rox.env.centralServices }} + secretName: additional-ca + {{- else }} + secretName: additional-ca-sensor + {{- end }} + - name: etc-ssl-volume + emptyDir: {} + - name: etc-pki-volume + emptyDir: {} + - name: tls-volume + secret: + secretName: scanner-v4-indexer-tls + - name: config-volume + configMap: + name: scanner-v4-indexer-config + - name: proxy-config-volume + secret: + secretName: proxy-config + optional: true + - name: tmp-volume + emptyDir: {} + - name: db-password + secret: + secretName: scanner-v4-db-password + {{- if ._rox.monitoring.openshift.enabled }} + - name: monitoring-tls + secret: + secretName: scanner-v4-indexer-monitoring-tls + {{- end }} + {{- include "srox.injectedCABundleVolume" . | nindent 6 }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-db-service.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-db-service.yaml new file mode 100644 index 0000000..f36bf4d --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-db-service.yaml @@ -0,0 +1,43 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._dbEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-db + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-db") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-db") | nindent 4 }} +spec: + type: ClusterIP + ports: + - name: tcp-db + port: 5432 + targetPort: 5432 + selector: + app: scanner-v4-db + +{{- if ._rox.env.istio }} +--- + +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-db-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-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-v4-db-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-db.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 5432 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-indexer-service.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-indexer-service.yaml new file mode 100644 index 0000000..7b3457b --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-08-indexer-service.yaml @@ -0,0 +1,55 @@ +{{- include "srox.init" . -}} +{{- if ._rox.scannerV4._indexerEnabled }} +apiVersion: v1 +kind: Service +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "service" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "service" "scanner-v4-indexer") | nindent 4 }} + {{- if ._rox.monitoring.openshift.enabled }} + service.beta.openshift.io/serving-cert-secret-name: scanner-v4-indexer-monitoring-tls + {{- end }} +spec: + selector: + app: scanner-v4-indexer + clusterIP: None + ports: + - name: grpc-scanner-v4-indexer + port: 8443 + targetPort: grpc + {{- if ._rox.scannerV4.exposeMonitoring }} + - name: monitoring + port: {{ ._rox.scannerV4.indexer.metricsPort }} + targetPort: monitoring + {{- end }} + {{- if ._rox.monitoring.openshift.enabled }} + - name: indexer-monitoring-tls + port: 9091 + targetPort: monitoring-tls + {{- end }} + +{{- if ._rox.env.istio }} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: scanner-v4-indexer-internal-no-istio-mtls + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "destinationrule" "scanner-v4-indexer-internal-no-istio-mtls") | nindent 4 }} + annotations: + stackrox.io/description: "Disable Istio mTLS for port 8443, since StackRox services use built-in mTLS." + {{- include "srox.annotations" (list . "destinationrule" "scanner-v4-indexer-internal-no-istio-mtls") | nindent 4 }} +spec: + host: scanner-v4-indexer.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8443 + tls: + mode: DISABLE +{{- end }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-09-indexer-hpa.yaml b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-09-indexer-hpa.yaml new file mode 100644 index 0000000..91e4832 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/02-scanner-v4-09-indexer-hpa.yaml @@ -0,0 +1,20 @@ +{{- include "srox.init" . -}} +{{- if and ._rox.scannerV4._indexerEnabled (not ._rox.scannerV4.indexer.autoscaling.disable) }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: scanner-v4-indexer + namespace: {{ .Release.Namespace }} + labels: + {{- include "srox.labels" (list . "horizontalpodautoscaler" "scanner-v4-indexer") | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "horizontalpodautoscaler" "scanner-v4-indexer") | nindent 4 }} +spec: + minReplicas: {{ ._rox.scannerV4.indexer.autoscaling.minReplicas }} + maxReplicas: {{ ._rox.scannerV4.indexer.autoscaling.maxReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: scanner-v4-indexer + targetCPUUtilizationPercentage: 150 +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/99-shared-openshift-monitoring.yaml b/rhacs/4.5.2/secured-cluster-services/templates/99-shared-openshift-monitoring.yaml new file mode 100644 index 0000000..2035970 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/99-shared-openshift-monitoring.yaml @@ -0,0 +1,65 @@ +{{- include "srox.init" . -}} +{{- if ._rox.monitoring.openshift.enabled -}} + {{- if (or ._rox.scannerV4._indexerEnabled ._rox.scannerV4._matcherEnabled) }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: "scanner-v4-monitor-{{ .Release.Namespace }}" + namespace: openshift-monitoring + labels: + {{- include "srox.labels" (list . "servicemonitor" (print "scanner-v4-monitor-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "servicemonitor" (print "scanner-v4-monitor-" .Release.Namespace)) | nindent 4 }} +spec: + endpoints: + {{- if ._rox.scannerV4._indexerEnabled }} + - interval: 30s + path: metrics + port: indexer-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: "scanner-v4-indexer.{{ .Release.Namespace }}.svc" + {{- end }} + {{- if ._rox.scannerV4._matcherEnabled }} + - interval: 30s + path: metrics + port: matcher-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: "scanner-v4-matcher.{{ .Release.Namespace }}.svc" + {{- end }} + selector: + matchLabels: + app.kubernetes.io/component: scanner-v4 + namespaceSelector: + matchNames: + - "{{ .Release.Namespace }}" +--- +{{/* TODO(ROX-22188): Switch to a ClusterRoleBinding to avoid leaking to + kube-system namespace. */ -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "rhacs-scanner-v4-auth-reader-{{ .Release.Namespace }}" + namespace: kube-system + labels: + {{- include "srox.labels" (list . "rolebinding" (print "rhacs-scanner-v4-auth-reader-" .Release.Namespace)) | nindent 4 }} + annotations: + {{- include "srox.annotations" (list . "rolebinding" (print "rhacs-scanner-v4-auth-reader-" .Release.Namespace)) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: scanner-v4 + namespace: "{{ .Release.Namespace }}" + {{- end }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/NOTES.txt b/rhacs/4.5.2/secured-cluster-services/templates/NOTES.txt new file mode 100644 index 0000000..e000c0f --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/NOTES.txt @@ -0,0 +1,44 @@ +{{- $_ := 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 }} + Scanner V4: {{ if ._rox._scannerV4Enabled -}} enabled {{- else -}} disabled {{- end }} +{{- if and ._rox._scannerV4Enabled ._rox._scannerV4Volume }} + Scanner V4 DB Volume: {{ ._rox._scannerV4Volume }} +{{- end }} + +{{ 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.5.2/secured-cluster-services/templates/_compatibility.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_compatibility.tpl new file mode 100644 index 0000000..c83ab2d --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_crypto.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_crypto.tpl new file mode 100644 index 0000000..4ac1fac --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_crypto.tpl @@ -0,0 +1,247 @@ +{{/* + 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 }} + {{ $msg := list }} + {{ $msg = append $msg (printf "Tried to generate certificate for %s, but no CA certificate is available." $spec.CN) }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "Providing the CA is required when certificates for new components need to be issued. This can happen, for instance, when enabling a new component such as Scanner V4 using 'helm upgrade'." }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "If the CA was generated by the Helm chart during initial installation, you need to retrieve these auto-generated values from the cluster and provide them to the 'helm upgrade' command. A command for retrieving the auto-generated values was included in the post-installation notes of the central-services Helm chart." }} + {{ $msg = append $msg "" }} + {{ $msg = append $msg "If the CA was generated outside of the Helm chart and provided during the installation of the central-services chart, then the same must be done when executing 'helm upgrade'. This can be achieved conveniently by specifying the '--reuse-values' flag to 'helm upgrade'." }} + {{ include "srox.fail" (join "\n" $msg) }} + {{ 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.5.2/secured-cluster-services/templates/_defaults.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_defaults.tpl new file mode 100644 index 0000000..2e9bdd2 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_defaults.tpl @@ -0,0 +1,58 @@ +{{/* + 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 }} + +{{/* + srox.ensureCentralEndpointContainsPort . + + Appends a default port to the configured central endpoint based on a very simply heuristic. + Specifically, it only checks if the provided endpoint contains a prefix "https://" and + the part after that prefix does not contain a double colon. + This heuristic is kept simple on purpose and does not correctly add the default ports in + case the host part is an IPv6 address. +*/}} +{{ define "srox.ensureCentralEndpointContainsPort" }} + {{ $ := . }} + + {{ $endpoint := $._rox.centralEndpoint }} + {{ if hasPrefix "https://" $endpoint }} + {{ $endpoint = trimPrefix "https://" $endpoint }} + {{ if not (contains ":" $endpoint) }} + {{ include "srox.note" (list $ (printf "Specified centralEndpoint %s does not contain a port, assuming port 443. If this is incorrect please specify the correct port." $._rox.centralEndpoint)) }} + {{ $_ := set $._rox "centralEndpoint" (printf "%s:443" $._rox.centralEndpoint) }} + {{ end }} + {{ end }} + +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_dict.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_dict.tpl new file mode 100644 index 0000000..bf14a6d --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_expand.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_expand.tpl new file mode 100644 index 0000000..9ed2531 --- /dev/null +++ b/rhacs/4.5.2/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 assumed 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._expandSingle $ $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.5.2/secured-cluster-services/templates/_format.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_format.tpl new file mode 100644 index 0000000..745fe47 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_helpers.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_helpers.tpl new file mode 100644 index 0000000..69e5316 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_helpers.tpl @@ -0,0 +1,94 @@ +{{/* + 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 -}} + +{{- define "srox.checkVersionRequirements" -}} + {{- $minHelmVersion := "3.9.0" -}} + {{- $ := . -}} + + {{- $helmVersion := "" -}} + {{- if and (not (kindIs "invalid" $.Capabilities.HelmVersion)) $.Capabilities.HelmVersion -}} + {{- $helmVersion = $.Capabilities.HelmVersion.Version -}} + {{- end -}} + + {{- if empty $helmVersion -}} + {{- $msg := printf "Failed to retrieve Helm version. Please make sure you are running Helm >= v%s." $minHelmVersion -}} + {{- if $._rox.allowUnsupportedHelmVersion -}} + {{- include "srox.warn" (list $ $msg) -}} + {{- else -}} + {{- include "srox.fail" $msg -}} + {{- end -}} + {{- else if semverCompare (printf "< %s" $minHelmVersion) $helmVersion -}} + {{- $msg := printf "Helm version requirements not satisfied. Your Helm %s is too old. Please update to Helm >= v%s." $helmVersion $minHelmVersion -}} + {{- if $._rox.allowUnsupportedHelmVersion -}} + {{- include "srox.warn" (list $ $msg) -}} + {{- else -}} + {{- include "srox.fail" $msg -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_image-pull-secrets.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_image-pull-secrets.tpl new file mode 100644 index 0000000..e758a70 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_image-pull-secrets.tpl @@ -0,0 +1,105 @@ +{{/* + srox.configureImagePullSecrets $ $cfgName $imagePullSecrets $secretResourceName $defaultSecretNames $namespace + + Configures image pull secrets. + + Note: This function must be called late in srox.init, as we rely on "srox.configureImage" to collect the + set of all referenced images first. + + This function enriches $imagePullSecrets based on the exposed configuration parameters to contain: + + 1. Optionally (i.e. only if $imagePullSecrets contains a username), a `_dockerAuths` field, containing a map + from registry URLs to settings that contain login credentials. + The map contains registries for all images passed so far to srox.configureImage invocations. + + 2. A `_names` field, containing a list of Kubernetes secret names. The chart templates then use this field + to populate imagePullSecrets lists in ServiceAccount objects. + + The list contains the following secrets: + + - Secrets referenced via $imagePullSecrets.useExisting (unconditonally). + - Image pull secrets associated with the default service account (unless + $imagePullSecrets.useFromDefaultServiceAccount was set to false by the user). + - $secretResourceName, i.e. the secret optionally created by the chart templates. This name will be included + in the list either if username/password is provided (i.e. whe the chart ensures presence of the secret) OR + if the resource already exists in the namespace (for backward compatibility with versions 4.3 or earlier). + - $defaultSecretNames, only if the corresponding secrets already exist in the namespace (again, for backward + compatibility). + + Additionally, this function fails execution if the list resulting from first three bullet points + combined is empty. + +*/}} + +{{ 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 }} + +{{ if $imagePullSecrets._username }} + {{/* When username is present, existence of $secretResourceName will be assured by the templates; add to the list. */}} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretResourceName }} + + {{ $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 }} + +{{ 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 }} + +{{/* For backward compatibility, include those secrets which already exist. + In manifest installation mode, include them unconditionally, for lack of a better way. +*/}} +{{ range $secretName := append $defaultSecretNames $secretResourceName }} + {{ $secret := dict }} + {{ include "srox.safeLookup" (list $ $secret "v1" "Secret" $namespace $secretName) }} + {{ if or (eq $._rox.env.installMethod "manifest") $secret.result }} + {{ $imagePullSecretNames = append $imagePullSecretNames $secretName }} + {{ end }} +{{ end }} + +{{ $imagePullSecretNames = $imagePullSecretNames | uniq | sortAlpha }} +{{ $_ := set $imagePullSecrets "_names" $imagePullSecretNames }} + +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_images.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_images.tpl new file mode 100644 index 0000000..dced29d --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_init.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_init.tpl new file mode 100644 index 0000000..6085070 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_init.tpl @@ -0,0 +1,330 @@ +{{/* + 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 }} +{{ $_ := set $ "_rox" $rox }} + +{{ $configShape := $.Files.Get "internal/config-shape.yaml" | fromYaml }} +{{/* Only merge scanner config shapes if kubectl output is disabled */}} + {{ $configShapeScanner := $.Files.Get "internal/scanner-config-shape.yaml" | fromYaml }} + {{ $_ = include "srox.mergeInto" (list $configShape $configShapeScanner) }} + {{/* Only merge scanner-v4 config shapes if kubectl output is disabled and feature flag is enabled */}} + {{ $configShapeScannerV4 := $.Files.Get "internal/scanner-v4-config-shape.yaml" | fromYaml }} + {{ $_ = include "srox.mergeInto" (list $configShape $configShapeScannerV4) }} + +{{ $_ = include "srox.mergeInto" (list $rox $configShape) }} +{{ $_ = set $._rox "_configShape" $configShape }} + +{{/* 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 }} +{{ $_ = set $state "generated" dict }} +{{ $_ = set $state "notes" list }} +{{ $_ = set $state "warnings" list }} +{{ $_ = set $state "referencedImages" dict }} +{{ $_ = set $state "referencedStorageClasses" list }} +{{ $_ = set $._rox "_state" $state }} + +{{- include "srox.checkVersionRequirements" $ -}} + +{{/* Sanity checks.*/}} +{{- if not (kindIs "invalid" ._rox.clusterLabels) }} + {{- if not (kindIs "map" ._rox.clusterLabels) }} + {{ include "srox.fail" (printf "type mismatch: clusterLabels is a %s, but must be a dict" (kindOf ._rox.clusterLabels)) }} + {{- end }} + {{- range $key, $val := ._rox.clusterLabels }} + {{- if not (kindIs "string" $key) }} + {{ include "srox.fail" (printf "type mismatch: clusterLabels contains the key %v of type %s, but only string keys are allowed" $key (kindOf $key)) }} + {{- end }} + {{- if not (kindIs "string" $val) }} + {{ include "srox.fail" (printf "type mismatch: clusterLabels.%v is of type %s, but only string values are allowed" $key (kindOf $val)) }} + {{- end }} + {{- end }} +{{- end }} + +{{/* + 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.setInstallMethod" (list $) }} + +{{ include "srox.applyDefaults" $ }} +{{ include "srox.ensureCentralEndpointContainsPort" $ }} + +{{ include "srox.getStorageClasses" (list $) }} +{{ include "srox.getPVCs" (list $) }} + +{{/* Expand applicable config values */}} +{{ $expandables := $.Files.Get "internal/expandables.yaml" | fromYaml }} +{{ include "srox.expandAll" (list $ $rox $expandables) }} + +{{ $_ = include "srox.loadAnnotationTemplates" $ }} + +{{/* + 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.mergeInto" (list $._rox.collectorImagePullSecrets $._rox.imagePullSecrets) }} + +{{/* 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.configureImage" (list $ ._rox.image.scannerV4) }} + +{{ include "srox.initGlobalPrefix" (list $) }} + +{{/* +The following block checks for the validity of the provided init bundle. (`helm install ... -f `) +1. Throw an error if no init bundle was provided +2. Throw an error if the wrong init-bundle format was provided (user wrongly passed an operator-formatted init-bundle to helm). We detect the presence of an operator init bundle by checking for the Kubernetes secret annotation "init-bundle.stackrox.io/name", that suggests a user has wrongly used `helm install ... -f .` +3. Warn if the user specified both init bundles, e.g. `helm install ... -f -f ` +*/}} +{{ $operatorInitBundlePresent := hasKey (._rox.metadata).annotations "init-bundle.stackrox.io/name" }} +{{ $helmInitBundleNotPresent := empty ._rox.ca._cert }} +{{- if and $operatorInitBundlePresent $helmInitBundleNotPresent }} + {{ include "srox.fail" (list . "It seems an init bundle in the operator format has been provided. Note that this bundle format is ignored by the Helm chart. Make sure to provide an init bundle for Helm chart installation.") }} +{{- else if and (not $helmInitBundleNotPresent) $operatorInitBundlePresent }} + {{ include "srox.warn" (list . "It seems an init bundle in the operator format has been provided. Note that this bundle format is ignored by the Helm chart.") }} +{{- else if $helmInitBundleNotPresent }} + {{ include "srox.fail" (list . "A CA certificate must be specified") }} +{{- end }} + +{{/* 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 }} + +{{ $imagePullSecretNames := list }} + +{{ if eq ._rox.scanner.disable false }} +{{/* + Local scanner setup. + */}} + {{ $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.scanner "disable" true }} + {{ end }} + + {{ 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) }} + + {{ $imagePullSecretNames = append $imagePullSecretNames "stackrox-scanner" }} +{{ end }} +{{/* + Local Scanner v4 Indexer setup. + */}} + +{{ $scannerV4Cfg := $._rox.scannerV4 }} + + + +{{/* Disable scanner v4 always in kubectl outputs */}} + +{{/* Copy secured-cluster-style image configuration to what the Scanner V4 configuration machinery expects. */}} +{{ $_ := set $._rox.scannerV4 "image" $._rox.image.scannerV4 }} +{{ $_ := set $._rox.scannerV4.db "image" $._rox.image.scannerV4DB }} + +{{ include "srox.scannerV4Init" (list $ $scannerV4Cfg) }} +{{ if ._rox.scannerV4._dbEnabled }} + {{ include "srox.scannerV4Volume" $ }} +{{ end }} + +{{ if ._rox.scannerV4._indexerEnabled }} + {{ $imagePullSecretNames = append $imagePullSecretNames "stackrox-scanner-v4" }} +{{ end }} + +{{ if not (empty $imagePullSecretNames) }} + {{ $imagePullSecretNames = append $imagePullSecretNames "stackrox" }} + {{/* Note: This must happen late, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} + {{ include "srox.configureImagePullSecrets" (list $ "imagePullSecrets" $._rox.imagePullSecrets "secured-cluster-services-main" $imagePullSecretNames $.Release.Namespace) }} +{{ end }} + +{{/* Setup Image Pull Secrets. + + Note: This must happen late, as we rely on "srox.configureImage" to collect the + set of all referenced images first. */}} +{{ include "srox.configureImagePullSecrets" (list $ "mainImagePullSecrets" $._rox.mainImagePullSecrets "secured-cluster-services-main" (list "stackrox") $._rox._namespace) }} +{{ include "srox.configureImagePullSecrets" (list $ "collectorImagePullSecrets" $._rox.collectorImagePullSecrets "secured-cluster-services-collector" (list "stackrox" "collector-stackrox") $._rox._namespace) }} + +{{ end }} + +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_injected-ca-bundle.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_injected-ca-bundle.tpl new file mode 100644 index 0000000..f831139 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_labels.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_labels.tpl new file mode 100644 index 0000000..f677d69 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_labels.tpl @@ -0,0 +1,31 @@ +{{/* + srox._labels $ $labels $extraLabels $objType $objName $forPod + + Writes all applicable [pod] labels (including default labels) for $objType/$objName + into $labels. Pod labels are written iff $forPod is true. + The dict $extraLabels can be used for specifying additional labels which + can be modified using `customize` entries before before they are added to $labels. + */}} +{{ define "srox._labels" }} +{{ $ := index . 0 }} +{{ $labels := index . 1 }} +{{ $extraLabels := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $forPod := index . 5 }} +{{ $_ := 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 "^.*/(\\d{2}-)?(admission-control|collector|sensor|scanner-v4)[^/]*\\.yaml" $.Template.Name "${2}" }} +{{ 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 $extraLabels $objType $objName $metadataNames) }} +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_lookup.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_lookup.tpl new file mode 100644 index 0000000..17f6306 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_metadata.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_metadata.tpl new file mode 100644 index 0000000..e97d70d --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_metadata.tpl @@ -0,0 +1,307 @@ +{{/* + srox.labels $ $objType $objName [ $extraLabels ] + + Format labels for $objType/$objName as YAML. This takes into consideration the $extraLabels, + if provided, plus labels added using the generic `customize` configuration mechanism. + Note that provided $extraLabels can be modified by the user via `customize`. + + Note that pod resources are treated specially when it comes to customizing labels. + For enabling the user to define labels which shall only be applied to pods belonging + to a specific workload, the following rules apply for the Helm chart templates: + + - use the "srox.podLabels" template for injecting labels into pod templates and + - use the "srox.labels" template for injecting labels into all other resources. + + The user of the Helm charts may define `labels` within the `customize` structure for any + resources rendered as part of the charts. Such labels defined for workloads, e.g. a deployment, + will be injected into the deployment resource *and* will also be inherited to the pods belonging + to the workload. On the other hand, labels defined via `podLabels` are only meaningful for workload + resources and are only injected into the respective pods. + */}} +{{- define "srox.labels" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraLabels := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraLabels = default dict (index . 3) -}} + {{- end -}} + {{- $labels := dict -}} + {{- $_ := include "srox._labels" (list $ $labels $extraLabels $objType $objName false) }} + {{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.podLabels $ $objType $objName [ $extraLabels ] + + Format pod labels for $objType/$objName as YAML. This takes into consideration the $extraLabels, + if provided, plus labels added using the generic `customize` configuration mechanism. + Note that provided $extraLabels can be modified by the user via `customize`. + + See the description above for the template "srox.labels" for an explanation of the differences between + "srox.labels" and "srox.podLabels". + */}} +{{- define "srox.podLabels" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraLabels := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraLabels = default dict (index . 3) -}} + {{- end -}} + {{- $labels := dict -}} + {{- $_ := include "srox._labels" (list $ $labels $extraLabels $objType $objName true) }} + {{- toYaml $labels -}} +{{- end -}} + +{{/* + srox.annotations $ $objType $objName [ $extraAnnotations ] + + Format annotations for $objType/$objName as YAML. This takes into consideration the $extraAnnotations, + if provided, plus annotations added using the generic `customize` configuration mechanism. + Note that provided $extraAnnotations can be modified by the user via `customize`. + + Note that pod resources are treated specially when it comes to customizing annotations. + For enabling the user to define annotations which shall only be applied to pods belonging + to a specific workload, the following rules apply for the Helm chart templates: + + - use the "srox.podAnnotations" template for injecting annotations into pod templates and + - use the "srox.annotations" template for injecting annotations into all other resources. + + The user of the Helm charts may define `annotations` within the `customize` structure for any + resources rendered as part of the charts. Such annotations defined for workloads, e.g. a deployment, + will be injected into the deployment resource *and* will also be inherited to the pods belonging + to the workload. On the other hand, annotations defined via `podAnnotations` are only meaningful + for workload resources and are only injected into the respective pods. + */}} +{{- define "srox.annotations" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraAnnotations := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraAnnotations = default dict (index . 3) -}} + {{- end -}} + {{- $annotations := dict -}} + {{- $_ := include "srox._annotations" (list $ $annotations $extraAnnotations $objType $objName false) -}} + {{- toYaml $annotations -}} +{{- end -}} + +{{/* + srox.podAnnotations $ $objType $objName [ $extraAnnotations ] + + Format pod annotations for $objType/$objName as YAML. This takes into consideration the $extraAnnotations, + if provided, plus annotations added using the generic `customize` configuration mechanism. + Note that provided $extraAnnotations can be modified by the user via `customize`. + + See the description above for the template "srox.annotations" for an explanation of the differences between + "srox.annotations" and "srox.podAnnotations". + */}} +{{- define "srox.podAnnotations" -}} + {{- $ := index . 0 -}} + {{- $objType := index . 1 -}} + {{- $objName := index . 2 -}} + {{- $extraAnnotations := dict -}} + {{- if gt (len .) 3 -}} + {{- $extraAnnotations = default dict (index . 3) -}} + {{- end -}} + {{- $annotations := dict -}} + {{- $_ := include "srox._annotations" (list $ $annotations $extraAnnotations $objType $objName 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 $extraAnnotations $objType $objName $forPod + + Writes all applicable [pod] annotations (including default annotations) for + $objType/$objName into $annotations. Pod labels are written iff $forPod is true. + The dict $extraAnnotations can be used for specifying additional annotations which + can be modified by the user using `customize` entries before before they are added to $annotations. + */}} +{{ define "srox._annotations" }} +{{ $ := index . 0 }} +{{ $annotations := index . 1 }} +{{ $extraAnnotations := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $forPod := index . 5 }} +{{ $_ := 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 $extraAnnotations $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 dict $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 $extraMetadata $objType $objName $metadataNames + + Writes custom key/value metadata to $metadata by consulting $extraMetadata in addition to 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 }} +{{ $extraMetadata := index . 2 }} +{{ $objType := index . 3 }} +{{ $objName := index . 4 }} +{{ $metadataNames := index . 5 }} + +{{ $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 $extraMetadata $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. */ -}} + {{- if hasPrefix "stackrox-" $name -}} + {{- printf "%s-%s" $._rox.globalPrefix (trimPrefix "stackrox-" $name) -}} + {{- else if hasPrefix "stackrox:" $name -}} + {{- printf "%s:%s" $._rox.globalPrefix (trimPrefix "stackrox:" $name) -}} + {{- else -}} + {{- include "srox.fail" (printf "Unknown naming convention for global resource %q." $name) -}} + {{- end -}} +{{- 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 -}} + +{{/* + srox.getAnnotationTemplate . $name $out + + Retrieve the annotation template with the given $name and store it in the provided $out parameter. + */}} +{{ define "srox.getAnnotationTemplate" }} + {{ $ := index . 0 }} + {{ $name := index . 1 }} + {{ $out := index . 2 }} + {{ if kindIs "invalid" $._rox._annotationTemplates }} + {{ include "srox.fail" "Annotation templates not initialized" }} + {{ end }} + {{ $annotationTemplates := get $._rox._annotationTemplates $name }} + {{ if not $annotationTemplates }} + {{ include "srox.fail" (printf "Annotation template %q does not exist in internal/annotations/" $name) }} + {{ end }} + {{ range $key, $value := $annotationTemplates }} + {{ $_ := set $out $key $value }} + {{ end }} +{{ end }} + +{{/* + srox.loadAnnotationTemplates . + + Load the annotation templates from `internal/annotations` and store them within $._rox. + The templates can later be retrieved with `srox.getAnnotationTemplate`. + */}} +{{ define "srox.loadAnnotationTemplates" }} + {{ $ := . }} + {{ if kindIs "invalid" $._rox._annotationTemplates }} + {{ $_ := set $._rox "_annotationTemplates" dict }} + {{ end }} + {{ range $fileName, $annotations := $.Files.Glob "internal/annotations/*.yaml" }} + {{ $name := trimSuffix ".yaml" (base $fileName) }} + {{ $_ := set $._rox._annotationTemplates $name ($annotations | toString | fromYaml) }} + {{ end }} +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_openshift.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_openshift.tpl new file mode 100644 index 0000000..85201cb --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_psp.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_psp.tpl new file mode 100644 index 0000000..bffb2a0 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_pvcs.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_pvcs.tpl new file mode 100644 index 0000000..ad40204 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_pvcs.tpl @@ -0,0 +1,20 @@ +{{/* + srox.getPVCs $ + + This function attempts to retrieve information about all available PVCs in the + current namespace + + $._rox.env.pvcs.names: A list of PVC names. + */}} +{{- define "srox.getPVCs" -}} + + {{- $ := index . 0 -}} + {{- $pvcNames := list -}} + {{- $lookupResult := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupResult "v1" "PersistentVolumeClaim" $._rox._namespace "") -}} + {{- range $pvc := get ($lookupResult.result | default dict) "items" | default list -}} + {{- $pvcNames = append $pvcNames $pvc.metadata.name -}} + {{- end -}} + {{- $_ := set $._rox.env.pvcs "names" $pvcNames -}} + +{{- end -}} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_reporting.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_reporting.tpl new file mode 100644 index 0000000..621e284 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_scanner-v4_init.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_scanner-v4_init.tpl new file mode 100644 index 0000000..323bfa4 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_scanner-v4_init.tpl @@ -0,0 +1,179 @@ +{{/* + srox.scannerV4Init . $scannerV4Config + + Initializes the Scanner v4 configuration. The scanner chart has two modes: Indexer and Matcher. + In Indexer mode, the Scanner pulls images and analyzes them to determine the base OS and installed packages + (i.e. it indexes the images). + In Matcher mode, the Scanner matches the found packages to known vulnerabilities to produce a Vulnerability Report. + Both modes require access to a PostgreSQL database. + + StackRox's Central service has two Scanner deployments: a Scanner running in Indexer mode and another + running in Matcher mode. In this context, the Helm chart can create its own certificates. + + StackRox's Secured Cluster services may deploy the Scanner in Indexer mode, only. + This would be done to access registries inaccessible to the Central cluster. + In this context, the Helm chart does not generate its own certificates. + + $scannerV4Config contains all values which are configured by the user. The structures can be viewed in the respective + config-shape. See internal/scanner-v4-config-shape.yaml. + */}} + +{{ define "srox.scannerV4Init" }} + +{{ $ := index . 0 }} +{{ $scannerV4Cfg := index . 1 }} +{{ $_ := false }} + +{{/* Sanity check. */}} +{{- if not (or (eq $.Chart.Name "stackrox-central-services") (eq $.Chart.Name "stackrox-secured-cluster-services")) -}} + {{- include "srox.fail" (printf "Unexpected Helm chart name %q." $.Chart.Name) -}} +{{- end -}} + +{{ $componentsCentralChart := dict "indexer" true "matcher" true }} +{{ $componentsSecuredClusterChart := dict "indexer" true "matcher" false }} + +{{/* These will be propagated up. */}} +{{ $components := dict "indexer" false "matcher" false }} +{{ $dbEnabled := false }} + +{{- if not $scannerV4Cfg.disable }} + {{/* Scanner V4 is switched on. */}} + + {{/* Scanner V4 component configuration depends on the chart. */}} + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{- $components = $componentsCentralChart -}} + {{- else -}} + {{- $components = $componentsSecuredClusterChart -}} + {{/* scannerV4.indexer.disable can be used to disable the deployment of indexer. + This is required for the operator use-case. */}} + {{- if $scannerV4Cfg.indexer.disable -}} + {{- $_ = set $components "indexer" false -}} + {{- end -}} + {{- end -}} + + {{/* Configure images, certificates and passwords as required. */}} + {{ if or (get $components "indexer") (get $components "matcher") }} + {{ include "srox.configureImage" (list $ $scannerV4Cfg.image) }} + {{ end }} + + {{ if get $components "indexer" }} + {{ $_ := set $scannerV4Cfg.indexer "image" $scannerV4Cfg.image }} + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{/* Only generate certificate when installing central-services. + For secured-cluster-services we don't configure certificates here, + instead they will be distributed at runtime by Sensor and Central. */}} + {{- if kindIs "invalid" $._rox.scannerV4.indexer.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-indexer-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.indexer.serviceTLS "generate" true -}} + {{- end -}} + {{- end -}} + {{- end }} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_INDEXER_SERVICE: Scanner V4 Indexer" "dnsBase" "scanner-v4-indexer" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.indexer.serviceTLS" $cryptoSpec) }} + {{- end -}} + {{ end }} + + {{ if get $components "matcher" }} + {{ $_ := set $scannerV4Cfg.matcher "image" $scannerV4Cfg.image }} + {{- if kindIs "invalid" $._rox.scannerV4.matcher.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-matcher-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.matcher.serviceTLS "generate" true -}} + {{- end -}} + {{- end }} + {{- end }} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_MATCHER_SERVICE: Scanner V4 Matcher" "dnsBase" "scanner-v4-matcher" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.matcher.serviceTLS" $cryptoSpec) }} + {{ end }} + + {{ if or (get $components "indexer") (get $components "matcher") }} + {{- if kindIs "invalid" $._rox.scannerV4.db.serviceTLS.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- if $.Release.IsUpgrade -}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-db-tls") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.db.serviceTLS "generate" true -}} + {{- end -}} + {{- end -}} + {{- end }} + {{- if kindIs "invalid" $._rox.scannerV4.db.password.generate }} + {{/* We need special handling here, because 'generate' will default to 'false' on upgrades. */}} + {{/* And in case scanner V4 was not deployed earlier, we need to make sure that these resources are correctly initialized. */}} + {{- $lookupOut := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupOut "v1" "Secret" $.Release.Namespace "scanner-v4-db-password") -}} + {{- if not $lookupOut.result -}} + {{/* If generate=null and the resource does not exist yet, attempt to create it. */}} + {{/* If lookup is not possible (e.g. in the operator), then 'generate' needs to be set correctly. */}} + {{- $_ := set $._rox.scannerV4.db.password "generate" true -}} + {{- end -}} + {{- end }} + + {{ include "srox.configureImage" (list $ $scannerV4Cfg.db.image) }} + {{ include "srox.configurePassword" (list $ "scannerV4.db.password") }} + + {{- if eq $.Chart.Name "stackrox-central-services" -}} + {{/* Only generate certificate when installing central-services. */}} + {{ $cryptoSpec := dict "CN" "SCANNER_V4_DB_SERVICE: Scanner V4 DB" "dnsBase" "scanner-v4-db" }} + {{ include "srox.configureCrypto" (list $ "scannerV4.db.serviceTLS" $cryptoSpec) }} + {{- end -}} + {{ end }} + +{{- if eq $.Chart.Name "stackrox-secured-cluster-services" -}} + {{/* Special handling for the secured-cluster-services chart in case it gets deployed + to the same namespace as central-services. */}} + {{ $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-v4-indexer from this chart and configuring sensor to use existing scanner-v4-indexer instance, if any.") }} + {{ $_ := set $components "indexer" false }} + {{ end }} +{{- end }} + +{{- end -}} {{/* if not $scannerV4Cfg.disable */}} + +{{/* Propagate information about which Scanner V4 components to deploy. */}} +{{- $_ := set $._rox "_scannerV4Enabled" (not $scannerV4Cfg.disable) -}} +{{- $_ := set $._rox.scannerV4 "_indexerEnabled" (get $components "indexer") -}} +{{- $_ := set $._rox.scannerV4 "_matcherEnabled" (get $components "matcher") -}} +{{- if or (get $components "indexer") (get $components "matcher") -}} + {{- $_ := set $._rox.scannerV4 "_dbEnabled" true -}} +{{- end -}} + +{{/* Provide some human-readable feedback regarding the Scanner V4 configuration to the user installing the Helm chart. */}} +{{- if and (get $components "indexer") (not (get $components "matcher")) -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "indexer" -}} +{{- else if and (not (get $components "indexer")) (get $components "matcher") -}} + {{/* Just here for completeness, not allowed currently. */}} + {{- $_ = set $._rox.scannerV4 "_installMode" "matcher" -}} +{{- else if and (get $components "indexer") (get $components "matcher") -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "indexer and matcher" -}} +{{- else -}} + {{- $_ = set $._rox.scannerV4 "_installMode" "" -}} +{{- end -}} + +{{- if not $scannerV4Cfg.disable }} + {{- if eq $._rox.scannerV4._installMode "" }} + {{ include "srox.note" (list $ (printf "Scanner V4 is enabled and Scanner V4 components are already deployed.")) }} + {{- else }} + {{ include "srox.note" (list $ (printf "Scanner V4 is enabled and the following Scanner V4 components will be deployed: %s" $._rox.scannerV4._installMode)) }} + {{- end }} +{{- end }} + +{{- end -}} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_scanner-v4_volume.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_scanner-v4_volume.tpl new file mode 100644 index 0000000..4d2a14b --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_scanner-v4_volume.tpl @@ -0,0 +1,113 @@ +{{/* + srox.scannerV4Volume $ + + Configures and initializes Scanner v4 persistence. + */}} +{{ define "srox.scannerV4Volume" }} +{{ $ := . }} +{{ $_ := set $ "_rox" $._rox }} + +{{ $scannerV4DBCfg := $._rox.scannerV4.db }} + +{{/* + Scanner v4 DB Volume config setup. + */}} +{{ $scannerV4DBVolumeCfg := dict }} +{{ $scannerV4DBVolumeHumanReadable := "" }} +{{ $pvcConfigShape := $._rox._configShape.scannerV4.db.persistence.persistentVolumeClaim }} +{{ $pvcDefaults := dict }} +{{- if eq $.Chart.Name "stackrox-central-services" -}} + {{ $pvcDefaults = $._rox._defaults.scannerV4DBPVCDefaults }} +{{- else -}} + {{ $pvcDefaults = $._rox.scannerV4DBPVCDefaults }} +{{- end -}} + +{{ $extraSettings := dict "createClaim" .Release.IsInstall }} +{{ if $._rox.env.storageClasses.default }} + {{ $_ = set $extraSettings "storageClass" $._rox.env.storageClasses.default }} +{{ end }} + +{{/* First we check that the persistence configuration provided by the user is sane in the sense that only one of the + supported backends emptyDir/hostPath/PVC is configured. */}} +{{ $persistenceBackendsConfigured := list }} +{{ if $scannerV4DBCfg.persistence.none }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured "emptyDir" }} +{{ end }} +{{ if $scannerV4DBCfg.persistence.hostPath }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured "hostPath" }} +{{ end }} +{{ if not (deepEqual $pvcConfigShape $scannerV4DBCfg.persistence.persistentVolumeClaim) }} + {{ $persistenceBackendsConfigured = append $persistenceBackendsConfigured (printf "PVC:%v" $scannerV4DBCfg.persistence.persistentVolumeClaim) }} +{{ end }} + +{{/* Sanity checks and defaulting. */}} +{{ if empty $persistenceBackendsConfigured }} + {{/* No persistence backend configured, pick a reasonable default. */}} + {{ if or $._rox.env.storageClasses.default (eq $.Chart.Name "stackrox-central-services") }} + {{/* Either a default StorageClass has been detected or we are currently rendering central-services. + In both cases we configure a PVC as persistence backend. */}} + {{ if $._rox.env.storageClasses.default }} + {{ include "srox.note" (list $ "Default StorageClass detected, a PVC will be used for Scanner V4 DB persistence.") }} + {{ else }} + {{ include "srox.note" (list $ "A PVC will be used for Scanner V4 DB persistence.") }} + {{ end }} + {{ if has $pvcDefaults.claimName $._rox.env.pvcs.names }} + {{ $_ = set $extraSettings "createClaim" false }} + {{ else }} + {{ $_ = set $extraSettings "createClaim" true }} + {{ end }} + {{ $_ = include "srox.mergeInto" (list $scannerV4DBCfg.persistence.persistentVolumeClaim $pvcConfigShape $extraSettings $pvcDefaults) }} + {{ else }} + {{/* No default StorageClass detected, currently rendering secured-cluster-services chart. */}} + {{ if has $pvcDefaults.claimName $._rox.env.pvcs.names }} + {{ include "srox.note" (list $ (printf "A PVC named %s already exists, will keep using it for Scanner V4 DB persistence." $pvcDefaults.claimName)) }} + {{ $_ = set $extraSettings "createClaim" false }} + {{ $_ = include "srox.mergeInto" (list $scannerV4DBCfg.persistence.persistentVolumeClaim $pvcConfigShape $extraSettings $pvcDefaults) }} + {{ else }} + {{/* Fallback to emptyDir. */}} + {{ include "srox.warn" (list $ (printf "No default StorageClass detected, using emptyDir as persistence backend for Scanner V4 DB. It is highly recommended to use a PVC instead. Please check the documentation for more information on this." )) }} + {{ $_ = set $scannerV4DBCfg.persistence "none" true }} + {{ end }} + {{ end }} +{{ else if gt (len $persistenceBackendsConfigured) 1 }} + {{ include "srox.fail" (printf "Invalid persistence configuration for Scanner V4 DB: more than one persistence backend configured (%v)" $persistenceBackendsConfigured) }} +{{ end }} + + +{{/* Update $scannerV4DBVolumeCfg depending on configured persistence backend. */}} +{{ if $scannerV4DBCfg.persistence.none }} + {{ include "srox.warn" (list $ "Persistence for Scanner V4 DB is turned off (it is using an emptyDir volume). Every deletion of the StackRox Scanner V4 DB pod will cause you to lose all your data. This is STRONGLY recommended against.") }} + {{ $_ := set $scannerV4DBVolumeCfg "emptyDir" dict }} + {{ $scannerV4DBVolumeHumanReadable = "emptyDir" }} +{{ else if $scannerV4DBCfg.persistence.hostPath }} + {{ if not $scannerV4DBCfg.nodeSelector }} + {{ include "srox.warn" (list $ "A hostPath volume will be used by the Scanner V4 DB. At the same time no node selector is specified. This is unlikely to work reliably.") }} + {{ end }} + {{ $_ := set $scannerV4DBVolumeCfg "hostPath" (dict "path" $scannerV4DBCfg.persistence.hostPath) }} + {{ $scannerV4DBVolumeHumanReadable = printf "hostPath (%s)" $scannerV4DBCfg.persistence.hostPath}} +{{ else }} + {{ if kindIs "invalid" $scannerV4DBCfg.persistence.persistentVolumeClaim.storageClass }} + {{ include "srox.note" (list $ "A PVC using the default storage class will be used for the Scanner V4 DB.") }} + {{ else }} + {{ include "srox.note" (list $ (printf "A PVC using the storage class %q will be used for the Scanner V4 DB." $scannerV4DBCfg.persistence.persistentVolumeClaim.storageClass)) }} + {{ end }} + {{ $scannerV4DBPVCCfg := $scannerV4DBCfg.persistence.persistentVolumeClaim }} + {{ $_ := include "srox.mergeInto" (list $scannerV4DBPVCCfg $extraSettings $pvcDefaults) }} + {{ $_ = set $scannerV4DBVolumeCfg "persistentVolumeClaim" (dict "claimName" $scannerV4DBPVCCfg.claimName) }} + {{ if $scannerV4DBPVCCfg.createClaim }} + {{ $_ = set $scannerV4DBCfg.persistence "_pvcCfg" $scannerV4DBPVCCfg }} + {{ end }} + {{ if $scannerV4DBPVCCfg.storageClass }} + {{ $_ = set $._rox._state "referencedStorageClasses" (mustAppend $._rox._state.referencedStorageClasses $scannerV4DBPVCCfg.storageClass | uniq) }} + {{ end }} + {{ $scannerV4DBVolumeHumanReadable = printf "PVC (%s)" $scannerV4DBPVCCfg.claimName }} +{{ end }} + +{{ $allPersistenceMethods := keys $scannerV4DBVolumeCfg | sortAlpha }} +{{ if ne (len $allPersistenceMethods) 1 }} +{{ end }} + +{{ $_ = set $scannerV4DBCfg.persistence "_volumeCfg" $scannerV4DBVolumeCfg }} +{{ $_ := set $._rox "_scannerV4Volume" $scannerV4DBVolumeHumanReadable }} + +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_scanner_init.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_scanner_init.tpl new file mode 100644 index 0000000..75fbe95 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/_set_install_method.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_set_install_method.tpl new file mode 100644 index 0000000..9475774 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_set_install_method.tpl @@ -0,0 +1,13 @@ +{{/* + srox.setInstallMethod $ + + Sets $.env.installMethod to one of: "operator", "helm", "manifest". +*/}} + +{{ define "srox.setInstallMethod" }} +{{ $ := index . 0 }} + + +{{ $_ := set $._rox.env "installMethod" "helm" }} + +{{ end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/_storage_classes.tpl b/rhacs/4.5.2/secured-cluster-services/templates/_storage_classes.tpl new file mode 100644 index 0000000..9183999 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/_storage_classes.tpl @@ -0,0 +1,36 @@ +{{/* + srox.getStorageClasses $ + + This function attempts to retrieve information about all available StorageClasses on the + cluster and write it to + + $._rox.env.storageClasses.all: A dict mapping storage class names to dicts containing + relevant properties of the storage class. + + $._rox.env.storageClasses.default: Either nil or a string containing the name of the + default StorageClass. + */}} +{{- define "srox.getStorageClasses" -}} + + {{- $ := index . 0 -}} + {{- $storageClasses := dict -}} + {{- $defaultStorageClass := "" -}} + + {{- $lookupResult := dict -}} + {{- $_ := include "srox.safeLookup" (list $ $lookupResult "storage.k8s.io/v1" "StorageClass" "" "") -}} + {{- range $sc := get ($lookupResult.result | default dict) "items" | default list -}} + {{- $storageClassName := $sc.metadata.name -}} + {{- $annotations := $sc.metadata.annotations | default dict -}} + {{- $isDefault := index $annotations "storageclass.kubernetes.io/is-default-class" | default false -}} + {{- $_ := set $storageClasses $storageClassName (dict "isDefault" $isDefault) -}} + {{- if and $isDefault (not $defaultStorageClass) -}} + {{- $defaultStorageClass = $storageClassName -}} + {{- end -}} + {{- end -}} + + {{ $_ := set $._rox.env.storageClasses "all" $storageClasses }} + {{- if ne $defaultStorageClass "" -}} + {{- $_ := set $._rox.env.storageClasses "default" $defaultStorageClass -}} + {{- end -}} + +{{- end -}} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/additional-ca-sensor.yaml b/rhacs/4.5.2/secured-cluster-services/templates/additional-ca-sensor.yaml new file mode 100644 index 0000000..aa1801c --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/admission-controller-netpol.yaml b/rhacs/4.5.2/secured-cluster-services/templates/admission-controller-netpol.yaml new file mode 100644 index 0000000..9e99276 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/admission-controller-netpol.yaml @@ -0,0 +1,48 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies }} +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 }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/admission-controller-pod-security.yaml b/rhacs/4.5.2/secured-cluster-services/templates/admission-controller-pod-security.yaml new file mode 100644 index 0000000..d4011f4 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/admission-controller-rbac.yaml b/rhacs/4.5.2/secured-cluster-services/templates/admission-controller-rbac.yaml new file mode 100644 index 0000000..1e4e11e --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/admission-controller-secret.yaml b/rhacs/4.5.2/secured-cluster-services/templates/admission-controller-secret.yaml new file mode 100644 index 0000000..3abcb9a --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/admission-controller.yaml b/rhacs/4.5.2/secured-cluster-services/templates/admission-controller.yaml new file mode 100644 index 0000000..2a81f3f --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/admission-controller.yaml @@ -0,0 +1,256 @@ +{{- 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: + {{- $annotations := dict "traffic.sidecar.istio.io/excludeInboundPorts" "8443" -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "restricted-v2" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "deployment" "admission-control" $annotations) | 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 ._rox.admissionControl.priorityClassName }} + priorityClassName: {{ ._rox.admissionControl.priorityClassName }} + {{- end }} + {{- if ._rox.admissionControl.hostAliases }} + hostAliases: {{ toYaml ._rox.admissionControl.hostAliases | 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: ROX_MEMLIMIT + 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 + - deployments/scale + - replicasets + - replicationcontrollers + - statefulsets + - daemonsets + - cronjobs + - jobs + {{- if ._rox.env.openshift }} + - deploymentconfigs + {{- end }} + namespaceSelector: + matchExpressions: + - key: namespace.metadata.stackrox.io/name + operator: NotIn + values: + - {{ ._rox._namespace }} + - 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.5.2/secured-cluster-services/templates/cluster-config.yaml b/rhacs/4.5.2/secured-cluster-services/templates/cluster-config.yaml new file mode 100644 index 0000000..20c81f6 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/collector-netpol.yaml b/rhacs/4.5.2/secured-cluster-services/templates/collector-netpol.yaml new file mode 100644 index 0000000..4fbebe7 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/collector-netpol.yaml @@ -0,0 +1,46 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies }} +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 }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/collector-pod-security.yaml b/rhacs/4.5.2/secured-cluster-services/templates/collector-pod-security.yaml new file mode 100644 index 0000000..d11ef4b --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/collector-rbac.yaml b/rhacs/4.5.2/secured-cluster-services/templates/collector-rbac.yaml new file mode 100644 index 0000000..5d4ffd9 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/collector-scc.yaml b/rhacs/4.5.2/secured-cluster-services/templates/collector-scc.yaml new file mode 100644 index 0000000..f593b22 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/collector-scc.yaml @@ -0,0 +1,49 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.env.openshift }} + +{{- 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 }} + auto-upgrade.stackrox.io/component: "sensor" + 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 }} + auto-upgrade.stackrox.io/component: "sensor" + 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.5.2/secured-cluster-services/templates/collector-secret.yaml b/rhacs/4.5.2/secured-cluster-services/templates/collector-secret.yaml new file mode 100644 index 0000000..6b07ea2 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/collector.yaml b/rhacs/4.5.2/secured-cluster-services/templates/collector.yaml new file mode 100644 index 0000000..a2f87b3 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/collector.yaml @@ -0,0 +1,234 @@ +{{- 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: + {{- $annotations := dict -}} + {{- if eq ._rox.env.openshift 4 }} + {{- $_ := set $annotations "openshift.io/required-scc" "privileged" -}} + {{- end }} + {{- include "srox.podAnnotations" (list . "daemonset" "collector" $annotations) | 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}} + {{- if ._rox.collector.priorityClassName }} + priorityClassName: {{ ._rox.collector.priorityClassName }} + {{- end }} + {{- if ._rox.collector.hostAliases }} + hostAliases: {{ toYaml ._rox.collector.hostAliases | 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 + {{- if eq ._rox.collector.collectionMethod "EBPF" }} + value: CORE_BPF + {{- else }} + value: {{ default "CORE_BPF" ._rox.collector.collectionMethod }} + {{- end }} + - 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: ROX_MEMLIMIT + 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 }} + securityContext: + privileged: true + 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.5.2/secured-cluster-services/templates/openshift-monitoring.yaml b/rhacs/4.5.2/secured-cluster-services/templates/openshift-monitoring.yaml new file mode 100644 index 0000000..6e04968 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/openshift-monitoring.yaml @@ -0,0 +1,136 @@ +{{- 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 + +--- + +{{- /* +The ServiceMonitor is placed into the openshift-monitoring namespace to comply with the +OpenShift monitoring namespace label requirements. This is an exception to the rule +that leaking resources into system namespaces should be avoided. +*/}} +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 }}" + +--- + +{{- /* +TODO(ROX-22188): Switch to a ClusterRoleBinding to avoid leaking to kube-system 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 }}" + +--- + +{{- /* +The PrometheusRule is placed into the openshift-monitoring namespace to comply with the +OpenShift monitoring namespace label requirements. This is an exception to the rule +that leaking resources into system namespaces should be avoided. +Note that we have an exception for this resource for the SRE webhook validation for +managed OpenShift clusters. +*/}} +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.5.2/secured-cluster-services/templates/sensor-compliance-rbac.yaml b/rhacs/4.5.2/secured-cluster-services/templates/sensor-compliance-rbac.yaml new file mode 100644 index 0000000..aec3ba8 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/sensor-compliance-rbac.yaml @@ -0,0 +1,36 @@ +{{- include "srox.init" . -}} + +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox:edit-compliance") }} + labels: + {{- include "srox.labels" (list . "clusterrole" "stackrox:edit-compliance") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrole" "stackrox:edit-compliance") | nindent 4 }} +rules: +- apiGroups: + - 'compliance.openshift.io' + resources: + - '*' + verbs: + - '*' +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "stackrox:manage-compliance") }} + labels: + {{- include "srox.labels" (list . "clusterrolebinding" "stackrox:manage-compliance") | nindent 4 }} + auto-upgrade.stackrox.io/component: "sensor" + annotations: + {{- include "srox.annotations" (list . "clusterrolebinding" "stackrox:manage-compliance") | nindent 4 }} +subjects: +- kind: ServiceAccount + name: sensor + namespace: {{ ._rox._namespace }} +roleRef: + kind: ClusterRole + name: {{ include "srox.globalResourceName" (list . "stackrox:edit-compliance") }} + apiGroup: rbac.authorization.k8s.io diff --git a/rhacs/4.5.2/secured-cluster-services/templates/sensor-netpol.yaml b/rhacs/4.5.2/secured-cluster-services/templates/sensor-netpol.yaml new file mode 100644 index 0000000..9bb695a --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/sensor-netpol.yaml @@ -0,0 +1,95 @@ +{{- include "srox.init" . -}} + +{{- if ._rox.network.enableNetworkPolicies }} +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 + {{- if ._rox.scannerV4._indexerEnabled }} + - podSelector: + matchLabels: + app: scanner-v4-indexer + {{- end }} + {{- 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 }} +{{- end }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/sensor-pod-security.yaml b/rhacs/4.5.2/secured-cluster-services/templates/sensor-pod-security.yaml new file mode 100644 index 0000000..e44a807 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/sensor-rbac.yaml b/rhacs/4.5.2/secured-cluster-services/templates/sensor-rbac.yaml new file mode 100644 index 0000000..ea23ed6 --- /dev/null +++ b/rhacs/4.5.2/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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:edit-workloads") }} + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:network-policies") }} + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:update-namespaces") }} + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:create-events") }} + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "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: {{ include "srox.globalResourceName" (list . "stackrox:review-tokens") }} + apiGroup: rbac.authorization.k8s.io diff --git a/rhacs/4.5.2/secured-cluster-services/templates/sensor-secret.yaml b/rhacs/4.5.2/secured-cluster-services/templates/sensor-secret.yaml new file mode 100644 index 0000000..848e1f2 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/templates/sensor.yaml b/rhacs/4.5.2/secured-cluster-services/templates/sensor.yaml new file mode 100644 index 0000000..e1963a7 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/templates/sensor.yaml @@ -0,0 +1,308 @@ +{{- 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 }} + {{- if eq ._rox.env.openshift 4 }} + openshift.io/required-scc: restricted-v2 + {{- end }} + spec: + {{- if ._rox.sensor._nodeSelector }} + nodeSelector: + {{- ._rox.sensor._nodeSelector | nindent 8 }} + {{- end}} + {{- if ._rox.sensor.tolerations }} + tolerations: + {{- toYaml ._rox.sensor.tolerations | nindent 8 }} + {{- end }} + {{- if ._rox.sensor.hostAliases }} + hostAliases: {{ toYaml ._rox.sensor.hostAliases | nindent 8 }} + {{- end }} + affinity: + {{- toYaml ._rox.sensor.affinity | nindent 8 }} + {{- if ._rox.sensor.priorityClassName }} + priorityClassName: {{ ._rox.sensor.priorityClassName }} + {{- end }} + {{- 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: ROX_MEMLIMIT + 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._scannerV4Enabled }} + - name: ROX_SCANNER_V4_INDEXER_ENDPOINT + value: {{ printf "scanner-v4-indexer.%s.svc:8443" .Release.Namespace }} + - name: ROX_SCANNER_V4 + value: "true" + {{- end }} + {{- 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 + {{- if ._rox.env.openshift }} + - name: sensor-bound-sa-token + mountPath: /var/run/secrets/openshift/serviceaccount + {{- end }} + - 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: {} + {{- if ._rox.env.openshift }} + - name: sensor-bound-sa-token + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + path: token + audience: openshift + expirationSeconds: 3600 + {{- end }} + - 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 + {{- 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: + {{- $annotations := dict -}} + {{- $_ := include "srox.getAnnotationTemplate" (list . "helm-hook_secret" $annotations) -}} + {{- include "srox.annotations" (list . "secret" "helm-effective-cluster-name" $annotations) | nindent 4 }} +stringData: + cluster-name: | + {{- ._rox.clusterName | nindent 4 }} +{{- end}} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/service-ca.yaml b/rhacs/4.5.2/secured-cluster-services/templates/service-ca.yaml new file mode 100644 index 0000000..7c01760 --- /dev/null +++ b/rhacs/4.5.2/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: | + {{- ._rox.ca._cert | nindent 4 }} diff --git a/rhacs/4.5.2/secured-cluster-services/templates/upgrader-serviceaccount.yaml b/rhacs/4.5.2/secured-cluster-services/templates/upgrader-serviceaccount.yaml new file mode 100644 index 0000000..05ba643 --- /dev/null +++ b/rhacs/4.5.2/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: {{ include "srox.globalResourceName" (list . "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.5.2/secured-cluster-services/values-private-scanner-v4.yaml.example b/rhacs/4.5.2/secured-cluster-services/values-private-scanner-v4.yaml.example new file mode 100644 index 0000000..abdc35e --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/values-private-scanner-v4.yaml.example @@ -0,0 +1,37 @@ +# # Private configuration options for Scanner V4 configured as part of the +# # secured-cluster-services Helm chart. +# +# scannerV4: +# +# # Configuration for the indexer component: +# indexer: +# # Internal "scanner-v4-indexer..svc" service TLS certificate for the Scanner V4 indexer 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---- +# +# # Configuration for the DB component: +# db: +# # The password to be used for authenticating database access. If this setting is omitted, a password will +# # be automatically generated upon initial deployment and the existing password will be used upon upgrades. +# password: +# value: +# +# # Internal "scanner-v4-db..svc" service TLS certificate for the Scanner V4 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---- diff --git a/rhacs/4.5.2/secured-cluster-services/values-private.yaml.example b/rhacs/4.5.2/secured-cluster-services/values-private.yaml.example new file mode 100644 index 0000000..ecdec21 --- /dev/null +++ b/rhacs/4.5.2/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.5.2/secured-cluster-services/values-public-scanner-v4.yaml.example b/rhacs/4.5.2/secured-cluster-services/values-public-scanner-v4.yaml.example new file mode 100644 index 0000000..4f8ba74 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/values-public-scanner-v4.yaml.example @@ -0,0 +1,177 @@ +# # Public configuration options for Scanner V4 configured as part of the +# # secured-cluster-services Helm chart. +# # +# # Image configuration for Scanner V4. +# # For a complete example, see the `values-public.yaml.example` file. +# image: +# # Configuration of the `scannerV4` image. +# scannerV4: +# registry: null +# name: null +# tag: null +# fullRef: null +# +# # Configuration of the `scannerV4DB` image. +# scannerV4DB: +# registry: null +# name: null +# tag: null +# fullRef: null +# +# scannerV4: +# +# # If this is set to false, Scanner V4 will be enabled and deployed. +# # Note that currently Scanner V4 cannot be used as the only scanner component. +# # Instead it must be currently deployed side-by-side with StackRox Scanner (scanner.disable=false). +# # If it is set to true, no other setting in this section will have any effect. +# disable: true +# +# # Scanner V4 consists of three components: indexer, matcher and db. +# # But when deployed as part of secured-cluster-services the only components +# # which can be deployed are indexer and db. Scanner V4 matcher is only supposed to +# # run as part of central-services. +# +# # Configuration for the indexer component: +# indexer: +# # The log level for the indexer deployment. This typically does not need to be changed. +# logLevel: INFO +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # 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-v4-indexer +# 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 +# +# # Default number of indexer replicas created upon startup. The actual number might be higher +# # or lower if autoscaling is enabled (see below). +# replicas: 3 +# +# # Settings related to autoscaling the indexer deployment. +# autoscaling: +# # If true, autoscaling will be disabled. None of the other settings in this section will +# # have any 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 indexer deployment. +# resources: +# requests: +# memory: "1500Mi" +# cpu: "1000m" +# limits: +# memory: "3Gi" +# cpu: "2000m" +# +# # Configuration for the DB component: +# db: +# +# # If you want to enforce indexer to only run on certain nodes, you can specify +# # a node selector here to make sure Scanner V4 can only be scheduled on Nodes with the +# # given label. +# nodeSelector: +# # This can contain arbitrary `label-key: label-value` pairs. +# role: scanner-v4 +# +# # If scheduling needs specific affinities, you can specify the corresponding affinities here. +# affinity: +# nodeAffinity: +# preferredDuringSchedulingIgnoredDuringExecution: +# # Scanner V4 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 +# +# # Resource settings for the DB deployment. +# resources: +# requests: +# cpu: "200m" +# memory: "2Gi" +# limits: +# cpu: "2000m" +# memory: "4Gi" +# +# # Configures how Scanner V4 stores its persistent data. +# # You can use a persistent volume claim (the recommended default), a host path, +# # or an emptyDir volume if Scanner V4 is running on a secured cluster without default StorageClass. +#  # +# # For performance reasons it is HIGHLY RECOMMENDED to use a PVC. +# # Following values show how to apply custom configuration to a PVC: +# persistence: +# persistentVolumeClaim: +# claimName: "scanner-v4-db" +# size: "50Gi" +# storageClass: "some-storage-class-name" diff --git a/rhacs/4.5.2/secured-cluster-services/values-public.yaml.example b/rhacs/4.5.2/secured-cluster-services/values-public.yaml.example new file mode 100644 index 0000000..15aed12 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/values-public.yaml.example @@ -0,0 +1,462 @@ +# 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. +## +## For example: +## +## clusterLabels: +## someKey: someStringValue +## +#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 quay.io/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: +# # - CORE_BPF +# # - NO_COLLECTION +# collectionMethod: CORE_BPF +# +# # 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 +# +# # 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.5.2/secured-cluster-services/values-scanner.yaml.example b/rhacs/4.5.2/secured-cluster-services/values-scanner.yaml.example new file mode 100644 index 0000000..f7f3eb6 --- /dev/null +++ b/rhacs/4.5.2/secured-cluster-services/values-scanner.yaml.example @@ -0,0 +1,92 @@ +# # NOTE: +# # The Scanner is not available in the secured clusters installed via roxctl. +# +# # 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.5.2/secured-cluster-services/values.yaml b/rhacs/4.5.2/secured-cluster-services/values.yaml new file mode 100644 index 0000000..3297a22 --- /dev/null +++ b/rhacs/4.5.2/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.