From 3ab84261e820236c275dd81f24c4d05b93dcb611 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 3 Aug 2023 15:34:19 -0600 Subject: [PATCH 01/60] integrating external secrets operator with gen3 helm charts --- .secrets.baseline | 57 ++++---- helm/arborist/Chart.yaml | 2 +- helm/arborist/README.md | 16 ++- helm/arborist/templates/_helpers.tpl | 24 +++- helm/arborist/templates/aws-config.yaml | 3 + .../templates/cluster-secret-store.yaml | 3 + helm/arborist/templates/external-secret.yaml | 18 +++ helm/arborist/values.yaml | 25 ++++ helm/audit/Chart.yaml | 2 +- helm/audit/README.md | 17 ++- helm/audit/templates/_helpers.tpl | 41 ++++-- helm/audit/templates/aws-config.yaml | 3 + .../audit/templates/cluster-secret-store.yaml | 3 + helm/audit/templates/external-secret.yaml | 35 +++++ helm/audit/templates/secrets.yaml | 2 +- helm/audit/values.yaml | 27 ++++ helm/aws-es-proxy/Chart.yaml | 2 +- helm/aws-es-proxy/README.md | 16 ++- helm/aws-es-proxy/templates/aws-config.yaml | 3 + helm/aws-es-proxy/templates/aws-es-proxy.yaml | 10 -- helm/aws-es-proxy/templates/deployment.yaml | 6 +- helm/aws-es-proxy/values.yaml | 25 ++-- helm/common/Chart.yaml | 2 +- helm/common/README.md | 2 +- helm/common/templates/_aws_config.tpl | 18 +++ .../templates/_cluster_secret_store.tpl | 24 ++++ helm/common/templates/_es_index_restore.tpl | 2 +- helm/common/templates/_restore_pgdump.tpl | 2 +- helm/fence/Chart.yaml | 2 +- helm/fence/README.md | 27 +++- helm/fence/templates/_helpers.tpl | 52 +++++++- helm/fence/templates/aws-config.yaml | 3 + helm/fence/templates/aws-userysnc-creds.yaml | 10 -- .../fence/templates/cluster-secret-store.yaml | 3 + helm/fence/templates/external-secret.yaml | 86 ++++++++++++ helm/fence/templates/usersync-cron.yaml | 123 +++++++++--------- helm/fence/values.yaml | 82 ++++++++---- helm/gen3/Chart.yaml | 2 +- helm/gen3/README.md | 23 ++-- helm/gen3/templates/aws-config.yaml | 3 + helm/gen3/templates/aws_config.yaml | 10 -- helm/gen3/templates/cluster-secret-store.yaml | 3 + helm/gen3/values.yaml | 41 +++--- helm/guppy/Chart.yaml | 2 +- helm/guppy/README.md | 10 +- helm/guppy/templates/aws-config.yaml | 3 + helm/guppy/templates/aws-creds.yaml | 13 -- helm/guppy/values.yaml | 11 +- helm/indexd/Chart.yaml | 2 +- helm/indexd/README.md | 13 +- helm/indexd/templates/_helpers.tpl | 24 +++- helm/indexd/templates/aws-config.yaml | 3 + .../templates/cluster-secret-store.yaml | 3 + helm/indexd/templates/external-secrets.yaml | 18 +++ helm/indexd/values.yaml | 29 ++++- helm/manifestservice/Chart.yaml | 2 +- helm/manifestservice/README.md | 16 ++- helm/manifestservice/templates/_helpers.tpl | 18 +++ .../manifestservice/templates/aws-config.yaml | 3 + .../templates/cluster-secret-store.yaml | 3 + .../templates/external-secret.yaml | 18 +++ ...-creds.yaml => manifestservice-creds.yaml} | 1 - helm/manifestservice/values.yaml | 25 ++++ helm/metadata/Chart.yaml | 2 +- helm/metadata/README.md | 12 +- helm/metadata/templates/_helpers.tpl | 22 ++++ helm/metadata/templates/aws-config.yaml | 3 + .../templates/cluster-secret-store.yaml | 3 + helm/metadata/templates/external-secret.yaml | 18 +++ helm/metadata/values.yaml | 17 +++ helm/peregrine/Chart.yaml | 2 +- helm/peregrine/README.md | 12 +- helm/peregrine/templates/_helpers.tpl | 24 +++- helm/peregrine/templates/aws-config.yaml | 3 + .../templates/cluster-secret-store.yaml | 3 + helm/peregrine/templates/external-secret.yaml | 18 +++ helm/peregrine/values.yaml | 18 +++ helm/requestor/Chart.yaml | 2 +- helm/requestor/README.md | 12 +- helm/requestor/templates/_helpers.tpl | 24 +++- helm/requestor/templates/aws-config.yaml | 3 + .../templates/cluster-secret-store.yaml | 3 + helm/requestor/templates/external-secret.yaml | 18 +++ helm/requestor/values.yaml | 17 +++ helm/sheepdog/Chart.yaml | 2 +- helm/sheepdog/README.md | 13 +- helm/sheepdog/templates/_helpers.tpl | 24 +++- helm/sheepdog/templates/aws-config.yaml | 3 + .../templates/cluster-secret-store.yaml | 3 + helm/sheepdog/templates/external-secrets.yaml | 18 +++ helm/sheepdog/values.yaml | 15 +++ helm/wts/Chart.yaml | 2 +- helm/wts/README.md | 13 +- helm/wts/templates/_helpers.tpl | 24 +++- helm/wts/templates/aws-config.yaml | 3 + helm/wts/templates/cluster-secret-store.yaml | 3 + helm/wts/templates/external-secret.yaml | 18 +++ helm/wts/values.yaml | 17 ++- 98 files changed, 1166 insertions(+), 305 deletions(-) create mode 100644 helm/arborist/templates/aws-config.yaml create mode 100644 helm/arborist/templates/cluster-secret-store.yaml create mode 100644 helm/arborist/templates/external-secret.yaml create mode 100644 helm/audit/templates/aws-config.yaml create mode 100644 helm/audit/templates/cluster-secret-store.yaml create mode 100644 helm/audit/templates/external-secret.yaml create mode 100644 helm/aws-es-proxy/templates/aws-config.yaml delete mode 100644 helm/aws-es-proxy/templates/aws-es-proxy.yaml create mode 100644 helm/common/templates/_aws_config.tpl create mode 100644 helm/common/templates/_cluster_secret_store.tpl create mode 100644 helm/fence/templates/aws-config.yaml delete mode 100644 helm/fence/templates/aws-userysnc-creds.yaml create mode 100644 helm/fence/templates/cluster-secret-store.yaml create mode 100644 helm/fence/templates/external-secret.yaml create mode 100644 helm/gen3/templates/aws-config.yaml delete mode 100644 helm/gen3/templates/aws_config.yaml create mode 100644 helm/gen3/templates/cluster-secret-store.yaml create mode 100644 helm/guppy/templates/aws-config.yaml delete mode 100644 helm/guppy/templates/aws-creds.yaml create mode 100644 helm/indexd/templates/aws-config.yaml create mode 100644 helm/indexd/templates/cluster-secret-store.yaml create mode 100644 helm/indexd/templates/external-secrets.yaml create mode 100644 helm/manifestservice/templates/aws-config.yaml create mode 100644 helm/manifestservice/templates/cluster-secret-store.yaml create mode 100644 helm/manifestservice/templates/external-secret.yaml rename helm/manifestservice/templates/{metadataservice-creds.yaml => manifestservice-creds.yaml} (99%) create mode 100644 helm/metadata/templates/aws-config.yaml create mode 100644 helm/metadata/templates/cluster-secret-store.yaml create mode 100644 helm/metadata/templates/external-secret.yaml create mode 100644 helm/peregrine/templates/aws-config.yaml create mode 100644 helm/peregrine/templates/cluster-secret-store.yaml create mode 100644 helm/peregrine/templates/external-secret.yaml create mode 100644 helm/requestor/templates/aws-config.yaml create mode 100644 helm/requestor/templates/cluster-secret-store.yaml create mode 100644 helm/requestor/templates/external-secret.yaml create mode 100644 helm/sheepdog/templates/aws-config.yaml create mode 100644 helm/sheepdog/templates/cluster-secret-store.yaml create mode 100644 helm/sheepdog/templates/external-secrets.yaml create mode 100644 helm/wts/templates/aws-config.yaml create mode 100644 helm/wts/templates/cluster-secret-store.yaml create mode 100644 helm/wts/templates/external-secret.yaml diff --git a/.secrets.baseline b/.secrets.baseline index 35b38431..4a5dde43 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2023-07-03T15:16:07Z", + "generated_at": "2023-08-03T21:28:39Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -186,15 +186,6 @@ "type": "Secret Keyword" } ], - "helm/aws-es-proxy/README.md": [ - { - "hashed_secret": "7c150ec931dbb741d0bfd6c8f4ef914026c0b44b", - "is_secret": false, - "is_verified": false, - "line_number": 61, - "type": "Secret Keyword" - } - ], "helm/common/README.md": [ { "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", @@ -356,7 +347,7 @@ "hashed_secret": "5d07e1b80e448a213b392049888111e1779a52db", "is_secret": false, "is_verified": false, - "line_number": 1916, + "line_number": 1944, "type": "Secret Keyword" } ], @@ -365,7 +356,7 @@ "hashed_secret": "1740c48fa3141d4851b14f97e3bc0f46f7670672", "is_secret": false, "is_verified": false, - "line_number": 118, + "line_number": 117, "type": "Secret Keyword" } ], @@ -445,35 +436,35 @@ "hashed_secret": "0d5cd5f3caaaf8354a6c62816b97bcae006d4bcf", "is_secret": false, "is_verified": false, - "line_number": 31, + "line_number": 33, "type": "Secret Keyword" }, { "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", "is_secret": false, "is_verified": false, - "line_number": 48, + "line_number": 53, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 50, + "line_number": 55, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 69, + "line_number": 74, "type": "Secret Keyword" }, { "hashed_secret": "1cc98556e7b1353c7bd08344f9190808b0d3d6d4", "is_secret": true, "is_verified": false, - "line_number": 101, + "line_number": 108, "type": "Secret Keyword" } ], @@ -491,7 +482,7 @@ "hashed_secret": "611f2e9064b518afdb23f201321f39029dd28917", "is_secret": false, "is_verified": false, - "line_number": 74, + "line_number": 86, "type": "Secret Keyword" } ], @@ -509,28 +500,28 @@ "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", "is_secret": false, "is_verified": false, - "line_number": 41, + "line_number": 43, "type": "Secret Keyword" }, { "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", "is_secret": false, "is_verified": false, - "line_number": 58, + "line_number": 63, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 60, + "line_number": 65, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 79, + "line_number": 84, "type": "Secret Keyword" } ], @@ -675,21 +666,21 @@ "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", "is_secret": false, "is_verified": false, - "line_number": 58, + "line_number": 63, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 60, + "line_number": 65, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 83, + "line_number": 88, "type": "Secret Keyword" } ], @@ -737,49 +728,49 @@ "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", "is_secret": false, "is_verified": false, - "line_number": 41, + "line_number": 43, "type": "Secret Keyword" }, { "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", "is_secret": false, "is_verified": false, - "line_number": 58, + "line_number": 63, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 60, + "line_number": 65, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 75, + "line_number": 80, "type": "Secret Keyword" }, { "hashed_secret": "c2c4e52c03a03ce3efeb21eb202d301018d4548e", "is_secret": false, "is_verified": false, - "line_number": 96, + "line_number": 101, "type": "Secret Keyword" }, { "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "is_secret": false, "is_verified": false, - "line_number": 103, + "line_number": 110, "type": "Secret Keyword" }, { "hashed_secret": "fa4497447699cdb0a81c66a7f21af28a75170195", "is_secret": false, "is_verified": false, - "line_number": 105, + "line_number": 112, "type": "Secret Keyword" } ], @@ -806,7 +797,7 @@ "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "is_secret": false, "is_verified": false, - "line_number": 229, + "line_number": 240, "type": "Secret Keyword" } ], diff --git a/helm/arborist/Chart.yaml b/helm/arborist/Chart.yaml index 08304731..25247023 100644 --- a/helm/arborist/Chart.yaml +++ b/helm/arborist/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.8 +version: 0.1.9 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/arborist/README.md b/helm/arborist/README.md index df556040..954eaa83 100644 --- a/helm/arborist/README.md +++ b/helm/arborist/README.md @@ -1,6 +1,6 @@ # arborist -![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.9](https://img.shields.io/badge/Version-0.1.9-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 arborist @@ -28,13 +28,22 @@ A Helm chart for gen3 arborist | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"JWKS_ENDPOINT","value":"http://fence-service/.well-known/jwks"}]` | Environment variables to pass to the container | | env[0] | string | `{"name":"JWKS_ENDPOINT","value":"http://fence-service/.well-known/jwks"}` | The URL of the JSON Web Key Set (JWKS) endpoint for authentication | +| externalSecrets | map | `{"arboristSmDbcreds":null}` | External Secrets settings. | +| externalSecrets.arboristSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | +| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | +| global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | +| global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | +| global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any arborist secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | @@ -81,6 +90,9 @@ A Helm chart for gen3 arborist | resources.requests | map | `{"cpu":0.1,"memory":"12Mi"}` | The amount of resources that the container requests | | resources.requests.cpu | string | `0.1` | The amount of CPU requested | | resources.requests.memory | string | `"12Mi"` | The amount of memory requested | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information for External Secrets. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | securityContext | map | `{}` | Security context to apply to the container | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"port":80,"type":"ClusterIP"}` | Kubernetes service information. | diff --git a/helm/arborist/templates/_helpers.tpl b/helm/arborist/templates/_helpers.tpl index 2aed27dc..1dfea5b1 100644 --- a/helm/arborist/templates/_helpers.tpl +++ b/helm/arborist/templates/_helpers.tpl @@ -77,4 +77,26 @@ Create the name of the service account to use {{- else }} {{- default .Values.postgres.password }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} + {{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "arborist-sm-dbcreds" -}} +{{- if .Values.externalSecrets.arboristSmDbcreds }} + {{- default .Values.externalSecrets.arboristSmDbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} diff --git a/helm/arborist/templates/aws-config.yaml b/helm/arborist/templates/aws-config.yaml new file mode 100644 index 00000000..398770d3 --- /dev/null +++ b/helm/arborist/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/arborist/templates/cluster-secret-store.yaml b/helm/arborist/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/arborist/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/arborist/templates/external-secret.yaml b/helm/arborist/templates/external-secret.yaml new file mode 100644 index 00000000..b0bca685 --- /dev/null +++ b/helm/arborist/templates/external-secret.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "arborist-sm-dbcreds" .}} +{{- end }} \ No newline at end of file diff --git a/helm/arborist/values.yaml b/helm/arborist/values.yaml index a2cbfcbf..0ca7ff07 100644 --- a/helm/arborist/values.yaml +++ b/helm/arborist/values.yaml @@ -4,6 +4,14 @@ # -- (map) Global configuration options. global: + # -- (map) AWS configuration + aws: + # -- (bool) Set to true if deploying to AWS. Controls ingress annotations. + enabled: false + # -- (string) Credentials for AWS stuff. + awsAccessKeyId: + # -- (string) Credentials for AWS stuff. + awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true # -- (map) Postgres database configuration. @@ -48,6 +56,23 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any arborist secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + arboristSmDbcreds: +# -- (map) Secret information for External Secrets. +secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID. Overrides global key. + awsSecretAccessKey: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: diff --git a/helm/audit/Chart.yaml b/helm/audit/Chart.yaml index 966a2573..4201f353 100644 --- a/helm/audit/Chart.yaml +++ b/helm/audit/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.9 +version: 0.1.10 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/audit/README.md b/helm/audit/README.md index e7d15409..9398de52 100644 --- a/helm/audit/README.md +++ b/helm/audit/README.md @@ -1,6 +1,6 @@ # audit -![Version: 0.1.9](https://img.shields.io/badge/Version-0.1.9-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.10](https://img.shields.io/badge/Version-0.1.10-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for Kubernetes @@ -36,13 +36,23 @@ A Helm chart for Kubernetes | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"DEBUG","value":"false"},{"name":"ARBORIST_URL","valueFrom":{"configMapKeyRef":{"key":"arborist_url","name":"manifest-global","optional":true}}}]` | Environment variables to pass to the container | +| externalSecrets | map | `{"auditG3auto":null,"auditSmDbcreds":null}` | External Secrets settings. | +| externalSecrets.auditG3auto | string | `nil` | Will override the name of the aws secrets manager secret. Default is "audit-g3auto" | +| externalSecrets.auditSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the chart, which is used as the name of resources created by the chart | -| global | map | `{"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | +| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | +| global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | +| global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | +| global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any audit secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | @@ -91,6 +101,9 @@ A Helm chart for Kubernetes | resources.requests | map | `{"cpu":0.2,"memory":"120Mi"}` | The amount of resources that the container requests | | resources.requests.cpu | string | `0.2` | The amount of CPU requested | | resources.requests.memory | string | `"120Mi"` | The amount of memory requested | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information for External Secrets. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | securityContext | map | `{}` | Security context for the containers in the pod | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | server.AWS_CREDENTIALS | map | `{}` | AWS credentials to access SQS queue. | diff --git a/helm/audit/templates/_helpers.tpl b/helm/audit/templates/_helpers.tpl index e255d758..08700261 100644 --- a/helm/audit/templates/_helpers.tpl +++ b/helm/audit/templates/_helpers.tpl @@ -67,16 +67,6 @@ Create the name of the service account to use {{- end }} {{- end }} - - -{{/* -Create the name of the service account to use -*/}} -{{- define "audit.secretName" -}} -{{- default "audit-g3auto" }} -{{- end }} - - {{/* Postgres Password lookup */}} @@ -87,4 +77,33 @@ Create the name of the service account to use {{- else }} {{- default .Values.postgres.password }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} + {{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Audit g3 Auto Secrets Manager Name +*/}} +{{- define "audit-g3auto" -}} +{{- default "audit-g3auto" .Values.externalSecrets.auditG3auto }} +{{- end }} + +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "audit-sm-dbcreds" -}} +{{- if .Values.externalSecrets.auditSmDbcreds }} + {{- default .Values.externalSecrets.auditSmDbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} diff --git a/helm/audit/templates/aws-config.yaml b/helm/audit/templates/aws-config.yaml new file mode 100644 index 00000000..398770d3 --- /dev/null +++ b/helm/audit/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/audit/templates/cluster-secret-store.yaml b/helm/audit/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/audit/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/audit/templates/external-secret.yaml b/helm/audit/templates/external-secret.yaml new file mode 100644 index 00000000..56c36756 --- /dev/null +++ b/helm/audit/templates/external-secret.yaml @@ -0,0 +1,35 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: audit-g3auto +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: audit-g3auto + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "audit-g3auto" .}} +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "audit-sm-dbcreds" .}} +{{- end }} \ No newline at end of file diff --git a/helm/audit/templates/secrets.yaml b/helm/audit/templates/secrets.yaml index 945c8d36..03a39c51 100644 --- a/helm/audit/templates/secrets.yaml +++ b/helm/audit/templates/secrets.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Secret metadata: - name: {{ include "audit.secretName" . }} + name: audit-g3auto labels: {{- include "audit.labels" . | nindent 4 }} stringData: diff --git a/helm/audit/values.yaml b/helm/audit/values.yaml index 97e70118..b8b31d23 100644 --- a/helm/audit/values.yaml +++ b/helm/audit/values.yaml @@ -3,6 +3,14 @@ # Declare variables to be passed into your templates. # -- (map) Global configuration options. global: + # -- (map) AWS configuration + aws: + # -- (bool) Set to true if deploying to AWS. Controls ingress annotations. + enabled: false + # -- (string) Credentials for AWS stuff. + awsAccessKeyId: + # -- (string) Credentials for AWS stuff. + awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true # -- (map) Postgres database configuration. @@ -47,6 +55,25 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any audit secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "audit-g3auto" + auditG3auto: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + auditSmDbcreds: +# -- (map) Secret information for External Secrets. +secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID. Overrides global key. + awsSecretAccessKey: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: diff --git a/helm/aws-es-proxy/Chart.yaml b/helm/aws-es-proxy/Chart.yaml index e8ac19ef..dc35848c 100644 --- a/helm/aws-es-proxy/Chart.yaml +++ b/helm/aws-es-proxy/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.6 +version: 0.1.7 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/aws-es-proxy/README.md b/helm/aws-es-proxy/README.md index 9cdb1805..161c15f2 100644 --- a/helm/aws-es-proxy/README.md +++ b/helm/aws-es-proxy/README.md @@ -1,6 +1,6 @@ # aws-es-proxy -![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.7](https://img.shields.io/badge/Version-0.1.7-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for AWS ES Proxy Service for gen3 @@ -26,7 +26,11 @@ A Helm chart for AWS ES Proxy Service for gen3 | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | esEndpoint | str | `"test.us-east-1.es.amazonaws.com"` | Elasticsearch endpoint in AWS | -| global | map | `{"ddEnabled":false,"environment":"default","minAvialable":1,"pdb":false}` | Global configuration options. | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"environment":"default","minAvialable":1,"pdb":false}` | Global configuration options. | +| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | +| global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | +| global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | +| global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.minAvialable | int | `1` | The minimum amount of pods that are available at all times if the PDB is deployed. | @@ -47,9 +51,9 @@ A Helm chart for AWS ES Proxy Service for gen3 | resources.requests.cpu | string | `0.1` | The amount of CPU requested | | resources.requests.memory | string | `"250Mi"` | The amount of memory requested | | revisionHistoryLimit | int | `2` | Number of old revisions to retain | -| secrets | map | `{"awsAccessKeyId":"","awsSecretAccessKey":""}` | Secret information | -| secrets.awsAccessKeyId | str | `""` | AWS access key ID | -| secrets.awsSecretAccessKey | str | `""` | AWS secret access key | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information to access AWS ES cluster. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"port":9200,"type":"ClusterIP"}` | Kubernetes service information. | | service.port | int | `9200` | The port number that the service exposes. | @@ -58,7 +62,7 @@ A Helm chart for AWS ES Proxy Service for gen3 | strategy.rollingUpdate.maxSurge | int | `1` | Number of additional replicas to add during rollout. | | strategy.rollingUpdate.maxUnavailable | int | `0` | Maximum amount of pods that can be unavailable during the update. | | volumeMounts | list | `[{"mountPath":"/root/.aws","name":"credentials","readOnly":true}]` | Volumes to mount to the pod. | -| volumes | list | `[{"name":"credentials","secret":{"secretName":"aws-es-proxy"}}]` | Volumes to attach to the pod | +| volumes | list | `nil` | Volumes to attach to the pod | ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/aws-es-proxy/templates/aws-config.yaml b/helm/aws-es-proxy/templates/aws-config.yaml new file mode 100644 index 00000000..4723e6b3 --- /dev/null +++ b/helm/aws-es-proxy/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end }} \ No newline at end of file diff --git a/helm/aws-es-proxy/templates/aws-es-proxy.yaml b/helm/aws-es-proxy/templates/aws-es-proxy.yaml deleted file mode 100644 index 734cb48c..00000000 --- a/helm/aws-es-proxy/templates/aws-es-proxy.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: aws-es-proxy -type: Opaque -stringData: - credentials: | - [default] - aws_access_key_id={{.Values.secrets.awsAccessKeyId}} - aws_secret_access_key={{ .Values.secrets.awsSecretAccessKey}} \ No newline at end of file diff --git a/helm/aws-es-proxy/templates/deployment.yaml b/helm/aws-es-proxy/templates/deployment.yaml index 3c74d70e..cd555b93 100644 --- a/helm/aws-es-proxy/templates/deployment.yaml +++ b/helm/aws-es-proxy/templates/deployment.yaml @@ -33,10 +33,10 @@ spec: {{- end }} spec: automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} - {{- with .Values.volumes }} volumes: - {{- toYaml . | nindent 8 }} - {{- end }} + - name: credentials + secret: + secretName: {{.Chart.Name}}-aws-config containers: - name: "esproxy" image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" diff --git a/helm/aws-es-proxy/values.yaml b/helm/aws-es-proxy/values.yaml index 5367ba70..e2f11aee 100644 --- a/helm/aws-es-proxy/values.yaml +++ b/helm/aws-es-proxy/values.yaml @@ -4,6 +4,14 @@ # -- (map) Global configuration options. global: + # -- (map) AWS configuration + aws: + # -- (bool) Set to true if deploying to AWS. Controls ingress annotations. + enabled: false + # -- (string) Credentials for AWS stuff. + awsAccessKeyId: + # -- (string) Credentials for AWS stuff. + awsSecretAccessKey: # -- (string) Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. environment: default # -- (bool) Whether Datadog is enabled. @@ -27,6 +35,13 @@ autoscaling: # -- (int) The target CPU utilization percentage for autoscaling targetCPUUtilizationPercentage: 80 +# -- (map) Secret information to access AWS ES cluster. +secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID. Overrides global key. + awsSecretAccessKey: + # -- (int) Number of replicas for the deployment. replicaCount: 1 @@ -47,9 +62,6 @@ automountServiceAccountToken: false # -- (list) Volumes to attach to the pod volumes: - - name: credentials - secret: - secretName: aws-es-proxy # -- (map) Docker image information. image: @@ -93,13 +105,6 @@ service: # -- (int) The port number that the service exposes. port: 9200 -# -- (map) Secret information -secrets: - # -- (str) AWS access key ID - awsAccessKeyId: "" - # -- (str) AWS secret access key - awsSecretAccessKey: "" - # Values to determine the labels that are used for the deployment, pod, etc. # -- (string) Valid options are "production" or "dev". If invalid option is set- the value will default to "dev". release: "production" diff --git a/helm/common/Chart.yaml b/helm/common/Chart.yaml index d55fd9fd..5007c4a7 100644 --- a/helm/common/Chart.yaml +++ b/helm/common/Chart.yaml @@ -15,7 +15,7 @@ type: library # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.7 +version: 0.1.8 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/common/README.md b/helm/common/README.md index e83608b2..a93a01fa 100644 --- a/helm/common/README.md +++ b/helm/common/README.md @@ -1,6 +1,6 @@ # common -![Version: 0.1.7](https://img.shields.io/badge/Version-0.1.7-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for provisioning databases in gen3 diff --git a/helm/common/templates/_aws_config.tpl b/helm/common/templates/_aws_config.tpl new file mode 100644 index 00000000..be48047c --- /dev/null +++ b/helm/common/templates/_aws_config.tpl @@ -0,0 +1,18 @@ +{{/* + Credentials for all AWS stuff. +*/}} +{{ define "common.awsconfig" -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{.Chart.Name}}-aws-config +type: Opaque +stringData: + credentials: | + [default] + aws_access_key_id={{ .Values.secrets.awsAccessKeyId | default .Values.global.aws.awsAccessKeyId}} + aws_secret_access_key={{ .Values.secrets.awsSecretAccessKey | default .Values.global.aws.awsSecretAccessKey}} +data: + access-key: {{ .Values.secrets.awsAccessKeyId | default .Values.global.aws.awsAccessKeyId | b64enc }} + secret-access-key: {{ .Values.secrets.awsSecretAccessKey | default .Values.global.aws.awsSecretAccessKey | b64enc }} +{{- end }} \ No newline at end of file diff --git a/helm/common/templates/_cluster_secret_store.tpl b/helm/common/templates/_cluster_secret_store.tpl new file mode 100644 index 00000000..03261581 --- /dev/null +++ b/helm/common/templates/_cluster_secret_store.tpl @@ -0,0 +1,24 @@ +{{/* + External Secrets Secret Store will allow all charts to allow for authentication to AWS Secrets Manager +*/}} +{{ define "common.secretstore" -}} +apiVersion: external-secrets.io/v1beta1 +kind: ClusterSecretStore +metadata: + name: {{.Chart.Name}}-secret-store +spec: + provider: + aws: + service: SecretsManager + region: us-east-1 + auth: + secretRef: + accessKeyIDSecretRef: + name: {{.Chart.Name}}-aws-config + key: access-key + namespace: default + secretAccessKeySecretRef: + name: {{.Chart.Name}}-aws-config + key: secret-access-key + namespace: default +{{- end }} \ No newline at end of file diff --git a/helm/common/templates/_es_index_restore.tpl b/helm/common/templates/_es_index_restore.tpl index 7953a627..06393d2c 100644 --- a/helm/common/templates/_es_index_restore.tpl +++ b/helm/common/templates/_es_index_restore.tpl @@ -21,7 +21,7 @@ spec: volumes: - name: cred-volume secret: - secretName: aws-config-{{ .Chart.Name }} + secretName: {{.Chart.Name}}-aws-config containers: - name: create-indices image: quay.io/cdis/awshelper:master diff --git a/helm/common/templates/_restore_pgdump.tpl b/helm/common/templates/_restore_pgdump.tpl index 7f849e0c..3f7b4967 100644 --- a/helm/common/templates/_restore_pgdump.tpl +++ b/helm/common/templates/_restore_pgdump.tpl @@ -17,7 +17,7 @@ spec: volumes: - name: cred-volume secret: - secretName: aws-config + secretName: {{.Chart.Name}}-aws-config containers: - name: restore-dbs image: quay.io/cdis/awshelper:master diff --git a/helm/fence/Chart.yaml b/helm/fence/Chart.yaml index 529a6d94..36d58d86 100644 --- a/helm/fence/Chart.yaml +++ b/helm/fence/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.13 +version: 0.1.14 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/fence/README.md b/helm/fence/README.md index d75bdfa4..013a4673 100644 --- a/helm/fence/README.md +++ b/helm/fence/README.md @@ -1,6 +1,6 @@ # fence -![Version: 0.1.13](https://img.shields.io/badge/Version-0.1.13-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.14](https://img.shields.io/badge/Version-0.1.14-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Fence @@ -89,13 +89,26 @@ A Helm chart for gen3 Fence | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"GEN3_UWSGI_TIMEOUT","valueFrom":{"configMapKeyRef":{"key":"uwsgi-timeout","name":"manifest-global","optional":true}}},{"name":"DD_AGENT_HOST","valueFrom":{"fieldRef":{"fieldPath":"status.hostIP"}}},{"name":"AWS_STS_REGIONAL_ENDPOINTS","value":"regional"},{"name":"PYTHONPATH","value":"/var/www/fence"},{"name":"GEN3_DEBUG","value":"False"},{"name":"FENCE_PUBLIC_CONFIG","valueFrom":{"configMapKeyRef":{"key":"fence-config-public.yaml","name":"manifest-fence","optional":true}}},{"name":"PGHOST","valueFrom":{"secretKeyRef":{"key":"host","name":"fence-dbcreds","optional":false}}},{"name":"PGUSER","valueFrom":{"secretKeyRef":{"key":"username","name":"fence-dbcreds","optional":false}}},{"name":"PGPASSWORD","valueFrom":{"secretKeyRef":{"key":"password","name":"fence-dbcreds","optional":false}}},{"name":"PGDB","valueFrom":{"secretKeyRef":{"key":"database","name":"fence-dbcreds","optional":false}}},{"name":"DBREADY","valueFrom":{"secretKeyRef":{"key":"dbcreated","name":"fence-dbcreds","optional":false}}},{"name":"DB","value":"postgresql://$(PGUSER):$(PGPASSWORD)@$(PGHOST):5432/$(PGDB)"},{"name":"INDEXD_PASSWORD","valueFrom":{"secretKeyRef":{"key":"fence","name":"indexd-service-creds"}}},{"name":"gen3Env","valueFrom":{"configMapKeyRef":{"key":"hostname","name":"manifest-global"}}}]` | Environment variables to pass to the container | +| externalSecrets | map | `{"fenceConfig":null,"fenceGoogleAppCredsSecret":null,"fenceGoogleStorageCredsSecret":null,"fenceJwtKeys":null,"fenceSmDbcreds":null}` | External Secrets settings. | +| externalSecrets.fenceConfig | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-config" | +| externalSecrets.fenceGoogleAppCredsSecret | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-google-app-creds-secret" | +| externalSecrets.fenceGoogleStorageCredsSecret | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-google-storage-creds-secret" | +| externalSecrets.fenceJwtKeys | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-jwt-keys" | +| externalSecrets.fenceSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","syncFromDbgap":false,"tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","syncFromDbgap":false,"tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | +| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | +| global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | +| global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | +| global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any fence secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | @@ -153,6 +166,9 @@ A Helm chart for gen3 Fence | resources.requests | map | `{"cpu":0.3,"memory":"128Mi"}` | The amount of resources that the container requests | | resources.requests.cpu | string | `0.3` | The amount of CPU requested | | resources.requests.memory | string | `"128Mi"` | The amount of memory requested | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information for Usersync and External Secrets. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS access key ID. Overrides global key. | | securityContext | map | `{}` | Security context for the containers in the pod | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"port":80,"type":"ClusterIP"}` | Kubernetes service information. | @@ -164,19 +180,16 @@ A Helm chart for gen3 Fence | serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | | serviceAccount.name | string | `"fence-sa"` | The name of the service account | | tolerations | list | `[]` | Tolerations for the pods | -| usersync | map | `{"addDbgap":false,"custom_image":null,"onlyDbgap":false,"schedule":"*/30 * * * *","secrets":{"awsAccessKeyId":"","awsSecretAccessKey":""},"slack_send_dbgap":false,"slack_webhook":"None","syncFromDbgap":false,"userYamlS3Path":"s3://cdis-gen3-users/helm-test/user.yaml","usersync":false}` | Configuration options for usersync cronjob. | +| usersync | map | `{"addDbgap":false,"custom_image":null,"onlyDbgap":false,"schedule":"*/30 * * * *","slack_send_dbgap":false,"slack_webhook":"None","syncFromDbgap":false,"userYamlS3Path":"s3://cdis-gen3-users/helm-test/user.yaml","usersync":true}` | Configuration options for usersync cronjob. | | usersync.addDbgap | bool | `false` | Force attempting a dbgap sync if "true", falls back on user.yaml | | usersync.custom_image | string | `nil` | To set a custom image for pulling the user.yaml file from S3. Default is the Gen3 Awshelper image. | | usersync.onlyDbgap | bool | `false` | Forces ONLY a dbgap sync if "true", IGNORING user.yaml | | usersync.schedule | string | `"*/30 * * * *"` | The cron schedule expression to use in the usersync cronjob. Runs every 30 minutes by default. | -| usersync.secrets | map | `{"awsAccessKeyId":"","awsSecretAccessKey":""}` | Secret information | -| usersync.secrets.awsAccessKeyId | str | `""` | AWS access key ID for usersync S3 bucket | -| usersync.secrets.awsSecretAccessKey | str | `""` | AWS secret access key for usersync S3 bucket | | usersync.slack_send_dbgap | bool | `false` | Will echo what files we are seeing on dbgap ftp to Slack. | | usersync.slack_webhook | string | `"None"` | Slack webhook endpoint used with certain jobs. | | usersync.syncFromDbgap | bool | `false` | Whether to sync data from dbGaP. | | usersync.userYamlS3Path | string | `"s3://cdis-gen3-users/helm-test/user.yaml"` | Path to the user.yaml file in S3. | -| usersync.usersync | bool | `false` | Whether to run Fence usersync or not. | +| usersync.usersync | bool | `true` | Whether to run Fence usersync or not. | | volumeMounts | list | `[{"mountPath":"/var/www/fence/local_settings.py","name":"old-config-volume","readOnly":true,"subPath":"local_settings.py"},{"mountPath":"/var/www/fence/fence_credentials.json","name":"json-secret-volume","readOnly":true,"subPath":"fence_credentials.json"},{"mountPath":"/var/www/fence/creds.json","name":"creds-volume","readOnly":true,"subPath":"creds.json"},{"mountPath":"/var/www/fence/config_helper.py","name":"config-helper","readOnly":true,"subPath":"config_helper.py"},{"mountPath":"/fence/fence/static/img/logo.svg","name":"logo-volume","readOnly":true,"subPath":"logo.svg"},{"mountPath":"/fence/fence/static/privacy_policy.md","name":"privacy-policy","readOnly":true,"subPath":"privacy_policy.md"},{"mountPath":"/var/www/fence/fence-config.yaml","name":"config-volume","readOnly":true,"subPath":"fence-config.yaml"},{"mountPath":"/var/www/fence/yaml_merge.py","name":"yaml-merge","readOnly":true,"subPath":"yaml_merge.py"},{"mountPath":"/var/www/fence/fence_google_app_creds_secret.json","name":"fence-google-app-creds-secret-volume","readOnly":true,"subPath":"fence_google_app_creds_secret.json"},{"mountPath":"/var/www/fence/fence_google_storage_creds_secret.json","name":"fence-google-storage-creds-secret-volume","readOnly":true,"subPath":"fence_google_storage_creds_secret.json"},{"mountPath":"/fence/keys/key/jwt_private_key.pem","name":"fence-jwt-keys","readOnly":true,"subPath":"jwt_private_key.pem"}]` | Volumes to mount to the container. | | volumes | list | `[{"name":"old-config-volume","secret":{"secretName":"fence-secret"}},{"name":"json-secret-volume","secret":{"optional":true,"secretName":"fence-json-secret"}},{"name":"creds-volume","secret":{"secretName":"fence-creds"}},{"configMap":{"name":"config-helper","optional":true},"name":"config-helper"},{"configMap":{"name":"logo-config"},"name":"logo-volume"},{"name":"config-volume","secret":{"secretName":"fence-config"}},{"name":"fence-google-app-creds-secret-volume","secret":{"secretName":"fence-google-app-creds-secret"}},{"name":"fence-google-storage-creds-secret-volume","secret":{"secretName":"fence-google-storage-creds-secret"}},{"name":"fence-jwt-keys","secret":{"secretName":"fence-jwt-keys"}},{"configMap":{"name":"privacy-policy"},"name":"privacy-policy"},{"configMap":{"name":"fence-yaml-merge","optional":true},"name":"yaml-merge"}]` | Volumes to attach to the container. | diff --git a/helm/fence/templates/_helpers.tpl b/helm/fence/templates/_helpers.tpl index f7011103..28372690 100644 --- a/helm/fence/templates/_helpers.tpl +++ b/helm/fence/templates/_helpers.tpl @@ -95,4 +95,54 @@ Create the name of the service account to use {{- else }} {{- default .Values.postgres.password }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} +{{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Fence JWT Keys Secrets Manager Name +*/}} +{{- define "fence-jwt-keys" -}} +{{- default "fence-jwt-keys" .Values.externalSecrets.fenceJwtKeys }} +{{- end }} + +{{/* + Fence Google App Creds Secrets Manager Name +*/}} +{{- define "fence-google-app-creds-secret" -}} +{{- default "fence-google-app-creds-secret" .Values.externalSecrets.fenceGoogleAppCredsSecret }} +{{- end }} + +{{/* + Fence Google Storage Creds Secrets Manager Name +*/}} +{{- define "fence-google-storage-creds-secret" -}} +{{- default "fence-google-storage-creds-secret" .Values.externalSecrets.fenceGoogleStorageCredsSecret }} +{{- end }} + +{{/* + Fence Config Secrets Manager Name +*/}} +{{- define "fence-config" -}} +{{- default "fence-config" .Values.externalSecrets.fenceConfig }} +{{- end }} + +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "fence-sm-dbcreds" -}} +{{- if .Values.externalSecrets.fenceSmDbcreds }} + {{- default .Values.externalSecrets.fenceSmDbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/helm/fence/templates/aws-config.yaml b/helm/fence/templates/aws-config.yaml new file mode 100644 index 00000000..398770d3 --- /dev/null +++ b/helm/fence/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/fence/templates/aws-userysnc-creds.yaml b/helm/fence/templates/aws-userysnc-creds.yaml deleted file mode 100644 index c6baff53..00000000 --- a/helm/fence/templates/aws-userysnc-creds.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: aws-config-fence -type: Opaque -stringData: - credentials: | - [default] - aws_access_key_id={{.Values.usersync.secrets.awsAccessKeyId}} - aws_secret_access_key={{.Values.usersync.secrets.awsSecretAccessKey}} \ No newline at end of file diff --git a/helm/fence/templates/cluster-secret-store.yaml b/helm/fence/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/fence/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/fence/templates/external-secret.yaml b/helm/fence/templates/external-secret.yaml new file mode 100644 index 00000000..f37d8287 --- /dev/null +++ b/helm/fence/templates/external-secret.yaml @@ -0,0 +1,86 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: fence-jwt-keys +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: fence-jwt-keys + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "fence-jwt-keys" .}} +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: fence-google-app-creds-secret +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: fence-google-app-creds-secret + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "fence-google-app-creds-secret" .}} +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: fence-google-storage-creds-secret +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: fence-google-storage-creds-secret + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "fence-google-storage-creds-secret" .}} +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: fence-config +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: fence-config + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "fence-config" .}} +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "fenceSmDbcreds" .}} +{{- end }} \ No newline at end of file diff --git a/helm/fence/templates/usersync-cron.yaml b/helm/fence/templates/usersync-cron.yaml index ef683944..3d8d8316 100644 --- a/helm/fence/templates/usersync-cron.yaml +++ b/helm/fence/templates/usersync-cron.yaml @@ -52,12 +52,71 @@ spec: emptyDir: {} - name: cred-volume secret: - secretName: aws-config-fence + secretName: {{.Chart.Name}}-aws-config initContainers: - name: wait-for-fence image: curlimages/curl:latest command: ["/bin/sh","-c"] args: ["while [ $(curl -sw '%{http_code}' http://fence-service -o /dev/null) -ne 200 ]; do sleep 5; echo 'Waiting for fence...'; done"] + - name: awshelper + image: {{ .Values.usersync.custom_image | default "quay.io/cdis/awshelper:master" }} + imagePullPolicy: Always + env: + - name: gen3Env + valueFrom: + configMapKeyRef: + name: manifest-global + key: hostname + - name: userYamlS3Path + value: {{ .Values.usersync.userYamlS3Path | quote }} + - name: slackWebHook + value: {{ .Values.usersync.slack_webhook | quote }} + volumeMounts: + - name: user-yaml + mountPath: /var/www/fence + - name: shared-data + mountPath: /mnt/shared + - name: cred-volume + mountPath: "/home/ubuntu/.aws/credentials" + subPath: credentials + command: ["/bin/bash" ] + args: + - "-c" + - | + GEN3_HOME=/home/ubuntu/cloud-automation + source "${GEN3_HOME}/gen3/lib/utils.sh" + gen3_load "gen3/gen3setup" + + if [ "${userYamlS3Path}" = 'none' ]; then + echo "using local user.yaml" + cp /var/www/fence/user.yaml /mnt/shared/user.yaml + else + # ----------------- + echo "awshelper downloading ${userYamlS3Path} to /mnt/shared/user.yaml" + n=0 + until [ $n -ge 5 ]; do + echo "Download attempt $n" + aws s3 cp "${userYamlS3Path}" /mnt/shared/user.yaml && break + n=$[$n+1] + sleep 2 + done + fi + if [[ ! -f /mnt/shared/user.yaml ]]; then + echo "awshelper failed to retrieve /mnt/shared/user.yaml" + exit 1 + fi + #----------- + echo "awshelper updating etl configmap" + if ! gen3 gitops etl-convert < /mnt/shared/user.yaml > /tmp/user.yaml; then + echo "ERROR: failed to generate ETL config" + exit 1 + fi + # kubectl delete configmap fence > /dev/null 2>&1 + # kubectl create configmap fence --from-file=/tmp/user.yaml + if [ "${slackWebHook}" != 'None' ]; then + curl -X POST --data-urlencode "payload={\"text\": \"AWSHelper: Syncing users on ${gen3Env}\"}" "${slackWebHook}" + fi + echo "Helper exit ok" containers: - name: usersync image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" @@ -102,7 +161,7 @@ spec: # Script always succeeds if it runs (echo exits with 0) - | echo 'options use-vc' >> /etc/resolv.conf - pip3 install SQLAlchemy==1.3.6 + # pip3 install SQLAlchemy==1.3.6 # can be removed once this is merged: https://github.com/uc-cdis/fence/pull/1096 if [[ "$SYNC_FROM_DBGAP" != "true" && "$ADD_DBGAP" != "true" ]]; then if [[ -f /mnt/shared/user.yaml ]]; then @@ -147,65 +206,5 @@ spec: fi echo "Exit code: $exitcode" exit "$exitcode" - - name: awshelper - image: {{ .Values.usersync.custom_image | default "quay.io/cdis/awshelper:master" }} - imagePullPolicy: Always - env: - - name: gen3Env - valueFrom: - configMapKeyRef: - name: manifest-global - key: hostname - - name: userYamlS3Path - value: {{ .Values.usersync.userYamlS3Path | quote }} - - name: slackWebHook - value: {{ .Values.usersync.slack_webhook | quote }} - volumeMounts: - - name: user-yaml - mountPath: /var/www/fence - - name: shared-data - mountPath: /mnt/shared - - name: cred-volume - mountPath: "/home/ubuntu/.aws/credentials" - subPath: credentials - command: ["/bin/bash" ] - args: - - "-c" - - | - GEN3_HOME=/home/ubuntu/cloud-automation - source "${GEN3_HOME}/gen3/lib/utils.sh" - gen3_load "gen3/gen3setup" - - if [ "${userYamlS3Path}" = 'none' ]; then - echo "using local user.yaml" - cp /var/www/fence/user.yaml /mnt/shared/user.yaml - else - # ----------------- - echo "awshelper downloading ${userYamlS3Path} to /mnt/shared/user.yaml" - n=0 - until [ $n -ge 5 ]; do - echo "Download attempt $n" - aws s3 cp "${userYamlS3Path}" /mnt/shared/user.yaml && break - n=$[$n+1] - sleep 2 - echo "test 1" - done - fi - if [[ ! -f /mnt/shared/user.yaml ]]; then - echo "awshelper failed to retrieve /mnt/shared/user.yaml" - exit 1 - fi - #----------- - echo "awshelper updating etl configmap" - if ! gen3 gitops etl-convert < /mnt/shared/user.yaml > /tmp/user.yaml; then - echo "ERROR: failed to generate ETL config" - exit 1 - fi - # kubectl delete configmap fence > /dev/null 2>&1 - # kubectl create configmap fence --from-file=/tmp/user.yaml - if [ "${slackWebHook}" != 'None' ]; then - curl -X POST --data-urlencode "payload={\"text\": \"AWSHelper: Syncing users on ${gen3Env}\"}" "${slackWebHook}" - fi - echo "Helper exit ok" restartPolicy: "Never" {{- end }} \ No newline at end of file diff --git a/helm/fence/values.yaml b/helm/fence/values.yaml index f0352346..287d28b1 100644 --- a/helm/fence/values.yaml +++ b/helm/fence/values.yaml @@ -4,6 +4,14 @@ # -- (map) Global configuration options. global: + # -- (map) AWS configuration + aws: + # -- (bool) Set to true if deploying to AWS. Controls ingress annotations. + enabled: false + # -- (string) Credentials for AWS stuff. + awsAccessKeyId: + # -- (string) Credentials for AWS stuff. + awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true # -- (map) Postgres database configuration. @@ -52,6 +60,53 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any fence secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "fence-jwt-keys" + fenceJwtKeys: + # -- (string) Will override the name of the aws secrets manager secret. Default is "fence-google-app-creds-secret" + fenceGoogleAppCredsSecret: + # -- (string) Will override the name of the aws secrets manager secret. Default is "fence-google-storage-creds-secret" + fenceGoogleStorageCredsSecret: + # -- (string) Will override the name of the aws secrets manager secret. Default is "fence-config" + fenceConfig: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + fenceSmDbcreds: + +# -- (map) Configuration options for usersync cronjob. +usersync: + # -- (bool) Whether to run Fence usersync or not. + usersync: true + # -- (string) The cron schedule expression to use in the usersync cronjob. Runs every 30 minutes by default. + schedule: "*/30 * * * *" + # -- (string) To set a custom image for pulling the user.yaml file from S3. Default is the Gen3 Awshelper image. + custom_image: + # -- (bool) Whether to sync data from dbGaP. + syncFromDbgap: false + # -- (bool) Force attempting a dbgap sync if "true", falls back on user.yaml + addDbgap: false + # -- (bool) Forces ONLY a dbgap sync if "true", IGNORING user.yaml + onlyDbgap: false + # -- (string) Path to the user.yaml file in S3. + userYamlS3Path: s3://cdis-gen3-users/helm-test/user.yaml + # -- (string) Slack webhook endpoint used with certain jobs. + slack_webhook: None + # -- (bool) Will echo what files we are seeing on dbgap ftp to Slack. + slack_send_dbgap: false + +# -- (map) Secret information for Usersync and External Secrets. +secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS access key ID. Overrides global key. + awsSecretAccessKey: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: @@ -80,33 +135,6 @@ postgresql: # -- (bool) Option to persist the dbs data. enabled: false -# -- (map) Configuration options for usersync cronjob. -usersync: - # -- (bool) Whether to run Fence usersync or not. - usersync: false - # -- (map) Secret information - secrets: - # -- (str) AWS access key ID for usersync S3 bucket - awsAccessKeyId: "" - # -- (str) AWS secret access key for usersync S3 bucket - awsSecretAccessKey: "" - # -- (string) The cron schedule expression to use in the usersync cronjob. Runs every 30 minutes by default. - schedule: "*/30 * * * *" - # -- (string) To set a custom image for pulling the user.yaml file from S3. Default is the Gen3 Awshelper image. - custom_image: - # -- (bool) Whether to sync data from dbGaP. - syncFromDbgap: false - # -- (bool) Force attempting a dbgap sync if "true", falls back on user.yaml - addDbgap: false - # -- (bool) Forces ONLY a dbgap sync if "true", IGNORING user.yaml - onlyDbgap: false - # -- (string) Path to the user.yaml file in S3. - userYamlS3Path: s3://cdis-gen3-users/helm-test/user.yaml - # -- (string) Slack webhook endpoint used with certain jobs. - slack_webhook: None - # -- (bool) Will echo what files we are seeing on dbgap ftp to Slack. - slack_send_dbgap: false - # -- (int) Number of desired replicas replicaCount: 1 diff --git a/helm/gen3/Chart.yaml b/helm/gen3/Chart.yaml index 5660c57c..51d65cd4 100644 --- a/helm/gen3/Chart.yaml +++ b/helm/gen3/Chart.yaml @@ -107,7 +107,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.18 +version: 0.1.19 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 98e37d69..248d5779 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -1,6 +1,6 @@ # gen3 -![Version: 0.1.18](https://img.shields.io/badge/Version-0.1.18-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.19](https://img.shields.io/badge/Version-0.1.19-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) Helm chart to deploy Gen3 Data Commons @@ -62,23 +62,17 @@ Helm chart to deploy Gen3 Data Commons | audit.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | aws-es-proxy.enabled | bool | `false` | Whether to deploy the aws-es-proxy subchart. | | aws-es-proxy.esEndpoint | str | `"test.us-east-1.es.amazonaws.com"` | Elasticsearch endpoint in AWS | -| aws-es-proxy.secrets | map | `{"awsAccessKeyId":"","awsSecretAccessKey":""}` | Secret information | -| aws-es-proxy.secrets.awsAccessKeyId | str | `""` | AWS access key ID for aws-es-proxy | -| aws-es-proxy.secrets.awsSecretAccessKey | str | `""` | AWS secret access key for aws-es-proxy | | fence.FENCE_CONFIG | map | `nil` | Configuration settings for Fence app | | fence.USER_YAML | string | `nil` | USER YAML. Passed in as a multiline string. | | fence.enabled | bool | `true` | Whether to deploy the fence subchart. | | fence.image | map | `{"repository":null,"tag":null}` | Docker image information. | | fence.image.repository | string | `nil` | The Docker image repository for the fence service. | | fence.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | -| fence.usersync | map | `{"addDbgap":false,"custom_image":null,"onlyDbgap":false,"schedule":"*/30 * * * *","secrets":{"awsAccessKeyId":"","awsSecretAccessKey":""},"slack_send_dbgap":false,"slack_webhook":"None","syncFromDbgap":false,"userYamlS3Path":"s3://cdis-gen3-users/helm-test/user.yaml","usersync":false}` | Configuration options for usersync cronjob. | +| fence.usersync | map | `{"addDbgap":false,"custom_image":null,"onlyDbgap":false,"schedule":"*/30 * * * *","slack_send_dbgap":false,"slack_webhook":"None","syncFromDbgap":false,"userYamlS3Path":"s3://cdis-gen3-users/helm-test/user.yaml","usersync":false}` | Configuration options for usersync cronjob. | | fence.usersync.addDbgap | bool | `false` | Force attempting a dbgap sync if "true", falls back on user.yaml | | fence.usersync.custom_image | string | `nil` | To set a custom image for pulling the user.yaml file from S3. Default is the Gen3 Awshelper image. | | fence.usersync.onlyDbgap | bool | `false` | Forces ONLY a dbgap sync if "true", IGNORING user.yaml | | fence.usersync.schedule | string | `"*/30 * * * *"` | The cron schedule expression to use in the usersync cronjob. Runs every 30 minutes by default. | -| fence.usersync.secrets | map | `{"awsAccessKeyId":"","awsSecretAccessKey":""}` | Secret information | -| fence.usersync.secrets.awsAccessKeyId | str | `""` | AWS access key ID for usersync S3 bucket | -| fence.usersync.secrets.awsSecretAccessKey | str | `""` | AWS secret access key for usersync S3 bucket | | fence.usersync.slack_send_dbgap | bool | `false` | Will echo what files we are seeing on dbgap ftp to Slack. | | fence.usersync.slack_webhook | string | `"None"` | Slack webhook endpoint used with certain jobs. | | fence.usersync.syncFromDbgap | bool | `false` | Whether to sync data from dbGaP. | @@ -90,12 +84,17 @@ Helm chart to deploy Gen3 Data Commons | gitops.json | string | `nil` | multiline string - gitops.json | | gitops.logo | string | `nil` | - logo in base64 | | gitops.sponsors | string | `nil` | | -| global.aws | map | `{"enabled":false}` | AWS configuration | +| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | +| global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | +| global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | +| global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Deploys postgres/elasticsearch for dev | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces in same cluster. | +| global.externalSecrets | map | `{"deploy":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override secrets you have deployed. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.portalApp | string | `"gitops"` | Portal application name. | @@ -190,9 +189,9 @@ Helm chart to deploy Gen3 Data Commons | revproxy.ingress.enabled | bool | `false` | Whether to create the custom revproxy ingress | | revproxy.ingress.hosts | list | `[{"host":"chart-example.local"}]` | Where to route the traffic. | | revproxy.ingress.tls | list | `[]` | To secure an Ingress by specifying a secret that contains a TLS private key and certificate. | -| secrets | map | `{"awsAccessKeyId":"test","awsSecretAccessKey":"test"}` | AWS credentials to access the db restore job S3 bucket | -| secrets.awsAccessKeyId | string | `"test"` | AWS access key. | -| secrets.awsSecretAccessKey | string | `"test"` | AWS secret access key. | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | sheepdog.enabled | bool | `true` | Whether to deploy the sheepdog subchart. | | sheepdog.image | map | `{"repository":null,"tag":null}` | Docker image information. | | sheepdog.image.repository | string | `nil` | The Docker image repository for the sheepdog service. | diff --git a/helm/gen3/templates/aws-config.yaml b/helm/gen3/templates/aws-config.yaml new file mode 100644 index 00000000..5fff9698 --- /dev/null +++ b/helm/gen3/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if .Values.global.aws.awsSecretAccessKey}} +{{ include "common.awsconfig" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/gen3/templates/aws_config.yaml b/helm/gen3/templates/aws_config.yaml deleted file mode 100644 index 3b51159c..00000000 --- a/helm/gen3/templates/aws_config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: aws-config -type: Opaque -stringData: - credentials: | - [default] - aws_access_key_id={{.Values.secrets.awsAccessKeyId}} - aws_secret_access_key={{ .Values.secrets.awsSecretAccessKey}} \ No newline at end of file diff --git a/helm/gen3/templates/cluster-secret-store.yaml b/helm/gen3/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..15558a80 --- /dev/null +++ b/helm/gen3/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.deploy }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index 00469112..9e9532cc 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -5,13 +5,12 @@ global: # -- (map) AWS configuration aws: + # -- (bool) Set to true if deploying to AWS. Controls ingress annotations. enabled: false - # # -- (map) Credentials for AWS - # account: - # # Prep move of these keys here. - # aws_access_key_id: - # aws_secret_access_key: - + # -- (string) Credentials for AWS stuff. + awsAccessKeyId: + # -- (string) Credentials for AWS stuff. + awsSecretAccessKey: # -- (bool) Deploys postgres/elasticsearch for dev dev: true postgres: @@ -50,6 +49,10 @@ global: dispatcherJobNum: 10 # -- (bool) Whether Datadog is enabled. ddEnabled: false + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override secrets you have deployed. + deploy: false # Dependancy Charts @@ -99,12 +102,6 @@ aws-es-proxy: enabled: false # -- (str) Elasticsearch endpoint in AWS esEndpoint: test.us-east-1.es.amazonaws.com - # -- (map) Secret information - secrets: - # -- (str) AWS access key ID for aws-es-proxy - awsAccessKeyId: "" - # -- (str) AWS secret access key for aws-es-proxy - awsSecretAccessKey: "" fence: # -- (bool) Whether to deploy the fence subchart. @@ -123,12 +120,6 @@ fence: usersync: # -- (bool) Whether to run Fence usersync or not. usersync: false - # -- (map) Secret information - secrets: - # -- (str) AWS access key ID for usersync S3 bucket - awsAccessKeyId: "" - # -- (str) AWS secret access key for usersync S3 bucket - awsSecretAccessKey: "" # -- (string) The cron schedule expression to use in the usersync cronjob. Runs every 30 minutes by default. schedule: "*/30 * * * *" # -- (string) To set a custom image for pulling the user.yaml file from S3. Default is the Gen3 Awshelper image. @@ -372,16 +363,16 @@ wts: # -- (string) Overrides the image tag whose default is the chart appVersion. tag: -# -- (map) AWS credentials to access the db restore job S3 bucket -secrets: - # -- (string) AWS access key. - awsAccessKeyId: test - # -- (string) AWS secret access key. - awsSecretAccessKey: test - # Disable persistence by default so we can spin up and down ephemeral environments postgresql: primary: persistence: # -- (bool) Option to persist the dbs data. enabled: false + +# -- (map) Secret information. +secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID. Overrides global key. + awsSecretAccessKey: \ No newline at end of file diff --git a/helm/guppy/Chart.yaml b/helm/guppy/Chart.yaml index ea90bf38..976494e2 100644 --- a/helm/guppy/Chart.yaml +++ b/helm/guppy/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.8 +version: 0.1.9 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/guppy/README.md b/helm/guppy/README.md index 25545b18..911be38f 100644 --- a/helm/guppy/README.md +++ b/helm/guppy/README.md @@ -1,6 +1,6 @@ # guppy -![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.9](https://img.shields.io/badge/Version-0.1.9-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Guppy Service @@ -36,7 +36,7 @@ A Helm chart for gen3 Guppy Service | datadogLogsInjection | bool | `true` | If enabled, the Datadog Agent will automatically inject Datadog-specific metadata into your application logs. | | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | -| dbRestore | bool | `true` | Whether or not to restore elasticsearch indices from a snapshot in s3 | +| dbRestore | bool | `false` | Whether or not to restore elasticsearch indices from a snapshot in s3 | | enableEncryptWhitelist | bool | `true` | Whether or not to enable encryption for specified fields | | encryptWhitelist | string | `"test1"` | A comma-separated list of fields to encrypt | | esEndpoint | string | `""` | Elasticsearch endpoint. | @@ -84,9 +84,9 @@ A Helm chart for gen3 Guppy Service | resources.requests.cpu | string | `0.1` | The amount of CPU requested | | resources.requests.memory | string | `"500Mi"` | The amount of memory requested | | revisionHistoryLimit | int | `2` | Number of old revisions to retain | -| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | AWS credentials to access the db restore job S3 bucket | -| secrets.awsAccessKeyId | string | `nil` | AWS access key. | -| secrets.awsSecretAccessKey | string | `nil` | AWS secret access key. | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information to access the db restore job S3 bucket. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"port":[{"name":"http","port":80,"protocol":"TCP","targetPort":8000}],"type":"ClusterIP"}` | Kubernetes service information. | | service.port | int | `[{"name":"http","port":80,"protocol":"TCP","targetPort":8000}]` | The port number that the service exposes. | diff --git a/helm/guppy/templates/aws-config.yaml b/helm/guppy/templates/aws-config.yaml new file mode 100644 index 00000000..4723e6b3 --- /dev/null +++ b/helm/guppy/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end }} \ No newline at end of file diff --git a/helm/guppy/templates/aws-creds.yaml b/helm/guppy/templates/aws-creds.yaml deleted file mode 100644 index 77f70daf..00000000 --- a/helm/guppy/templates/aws-creds.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} -apiVersion: v1 -kind: Secret -metadata: - name: aws-config-guppy -type: Opaque -stringData: - credentials: | - [default] - aws_access_key_id={{ .Values.secrets.awsAccessKeyId | default .Values.global.aws.awsAccessKeyId }} - aws_secret_access_key={{ .Values.secrets.awsSecretAccessKey | default .Values.global.aws.awsSecretAccessKey }} -{{- end }} - diff --git a/helm/guppy/values.yaml b/helm/guppy/values.yaml index 9857944f..fafd7c37 100644 --- a/helm/guppy/values.yaml +++ b/helm/guppy/values.yaml @@ -70,11 +70,13 @@ autoscaling: # -- (int) The target CPU utilization percentage for autoscaling targetCPUUtilizationPercentage: 80 -# -- (map) AWS credentials to access the db restore job S3 bucket +# -- (bool) Whether or not to restore elasticsearch indices from a snapshot in s3 +dbRestore: false +# -- (map) Secret information to access the db restore job S3 bucket. secrets: - # -- (string) AWS access key. + # -- (str) AWS access key ID. Overrides global key. awsAccessKeyId: - # -- (string) AWS secret access key. + # -- (str) AWS secret access key ID. Overrides global key. awsSecretAccessKey: # -- (int) Number of replicas for the deployment. @@ -195,9 +197,6 @@ enableEncryptWhitelist: true # -- (string) A comma-separated list of fields to encrypt encryptWhitelist: test1 -# -- (bool) Whether or not to restore elasticsearch indices from a snapshot in s3 -dbRestore: true - # Values to determine the labels that are used for the deployment, pod, etc. # -- (string) Valid options are "production" or "dev". If invalid option is set- the value will default to "dev". release: "production" diff --git a/helm/indexd/Chart.yaml b/helm/indexd/Chart.yaml index 54634c9d..8890042a 100644 --- a/helm/indexd/Chart.yaml +++ b/helm/indexd/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.10 +version: 0.1.11 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/indexd/README.md b/helm/indexd/README.md index ae4ea0bb..eaa6a92d 100644 --- a/helm/indexd/README.md +++ b/helm/indexd/README.md @@ -1,6 +1,6 @@ # indexd -![Version: 0.1.10](https://img.shields.io/badge/Version-0.1.10-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.11](https://img.shields.io/badge/Version-0.1.11-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 indexd @@ -27,8 +27,10 @@ A Helm chart for gen3 indexd | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | defaultPrefix | string | `"PREFIX/"` | default prefix for indexd | | env | list | `[{"name":"ARBORIST","value":"true"},{"name":"GEN3_DEBUG","value":"False"}]` | Environment variables to pass to the container | +| externalSecrets | map | `{"indexdSmDbcreds":null}` | External Secrets settings. | +| externalSecrets.indexdSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":true,"separate":true},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -38,6 +40,9 @@ A Helm chart for gen3 indexd | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":true,"separate":true}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `true` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any indexd secrets you have deployed. | +| global.externalSecrets.separate | string | `true` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | @@ -85,7 +90,9 @@ A Helm chart for gen3 indexd | resources.requests | map | `{"cpu":0.1,"memory":"12Mi"}` | The amount of resources that the container requests | | resources.requests.cpu | string | `0.1` | The amount of CPU requested | | resources.requests.memory | string | `"12Mi"` | The amount of memory requested | -| secrets | map | `{"userdb":{"fence":null,"sheepdog":null}}` | Values for indexd secret. | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"userdb":{"fence":null,"sheepdog":null}}` | Values for indexd secret. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID to access the db restore job S3 bucket. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID to access the db restore job S3 bucket. Overrides global key. | | securityContext | map | `{}` | Security context for the containers in the pod | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"port":80,"type":"ClusterIP"}` | Kubernetes service information. | diff --git a/helm/indexd/templates/_helpers.tpl b/helm/indexd/templates/_helpers.tpl index 0f83473c..21635df6 100644 --- a/helm/indexd/templates/_helpers.tpl +++ b/helm/indexd/templates/_helpers.tpl @@ -101,4 +101,26 @@ Create the name of the service account to use */}} {{- define "indexd-gateway-creds" -}} {{- default (randAlphaNum 32) .Values.secrets.userdb.gateway }} -{{- end }} \ No newline at end of file +{{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} + {{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "indexd-sm-dbcreds" -}} +{{- if .Values.externalSecrets.indexdSmDbcreds }} + {{- default .Values.externalSecrets.indexdSmDbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} diff --git a/helm/indexd/templates/aws-config.yaml b/helm/indexd/templates/aws-config.yaml new file mode 100644 index 00000000..4723e6b3 --- /dev/null +++ b/helm/indexd/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end }} \ No newline at end of file diff --git a/helm/indexd/templates/cluster-secret-store.yaml b/helm/indexd/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/indexd/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/indexd/templates/external-secrets.yaml b/helm/indexd/templates/external-secrets.yaml new file mode 100644 index 00000000..5921b810 --- /dev/null +++ b/helm/indexd/templates/external-secrets.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "indexd-sm-dbcreds" .}} +{{- end }} \ No newline at end of file diff --git a/helm/indexd/values.yaml b/helm/indexd/values.yaml index e9ee3d9c..4f4e0ef5 100644 --- a/helm/indexd/values.yaml +++ b/helm/indexd/values.yaml @@ -58,6 +58,28 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any indexd secrets you have deployed. + deploy: true + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: true + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + indexdSmDbcreds: + +# -- (map) Values for indexd secret. +secrets: + userdb: + fence: + sheepdog: + # gateway: + # -- (str) AWS access key ID to access the db restore job S3 bucket. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID to access the db restore job S3 bucket. Overrides global key. + awsSecretAccessKey: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: @@ -198,13 +220,6 @@ env: - name: "GEN3_DEBUG" value: "False" -# -- (map) Values for indexd secret. -secrets: - userdb: - fence: - sheepdog: - # gateway: - # -- (map) Values for overriding uwsgi settings uwsgi: listen: 1024 diff --git a/helm/manifestservice/Chart.yaml b/helm/manifestservice/Chart.yaml index a8920546..e01a6ba2 100644 --- a/helm/manifestservice/Chart.yaml +++ b/helm/manifestservice/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.10 +version: 0.1.11 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/manifestservice/README.md b/helm/manifestservice/README.md index 4e74a196..7969f749 100644 --- a/helm/manifestservice/README.md +++ b/helm/manifestservice/README.md @@ -1,6 +1,6 @@ # manifestservice -![Version: 0.1.10](https://img.shields.io/badge/Version-0.1.10-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.11](https://img.shields.io/badge/Version-0.1.11-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for Kubernetes @@ -33,9 +33,18 @@ A Helm chart for Kubernetes | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"REQUESTS_CA_BUNDLE","value":"/etc/ssl/certs/ca-certificates.crt"},{"name":"MANIFEST_SERVICE_CONFIG_PATH","value":"/var/gen3/config/config.json"},{"name":"GEN3_DEBUG","value":"False"}]` | Environment variables to pass to the container | -| global | map | `{"ddEnabled":false,"environment":"default","minAvialable":1,"pdb":false}` | Global configuration options. | +| externalSecrets | map | `{"manifestserviceG3auto":null}` | External Secrets settings. | +| externalSecrets.manifestserviceG3auto | string | `nil` | Will override the name of the aws secrets manager secret. Default is "manifestservice-g3auto" | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"minAvialable":1,"pdb":false}` | Global configuration options. | +| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | +| global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | +| global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | +| global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any manifestservice secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.minAvialable | int | `1` | The minimum amount of pods that are available at all times if the PDB is deployed. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | image | map | `{"pullPolicy":"Always","repository":"quay.io/cdis/manifestservice","tag":"2022.09"}` | Docker image information. | @@ -58,6 +67,9 @@ A Helm chart for Kubernetes | resources.requests.cpu | string | `0.1` | The amount of CPU requested | | resources.requests.memory | string | `"12Mi"` | The amount of memory requested | | revisionHistoryLimit | int | `2` | Number of old revisions to retain | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information for External Secrets. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"port":80,"type":"ClusterIP"}` | Kubernetes service information. | | service.port | int | `80` | The port number that the service exposes. | diff --git a/helm/manifestservice/templates/_helpers.tpl b/helm/manifestservice/templates/_helpers.tpl index d0d72644..b9702720 100644 --- a/helm/manifestservice/templates/_helpers.tpl +++ b/helm/manifestservice/templates/_helpers.tpl @@ -65,3 +65,21 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} +{{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Audit g3 Auto Secrets Manager Name +*/}} +{{- define "manifestservice-g3auto" -}} +{{- default "manifestservice-g3auto" .Values.externalSecrets.manifestserviceG3auto }} +{{- end }} diff --git a/helm/manifestservice/templates/aws-config.yaml b/helm/manifestservice/templates/aws-config.yaml new file mode 100644 index 00000000..398770d3 --- /dev/null +++ b/helm/manifestservice/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/manifestservice/templates/cluster-secret-store.yaml b/helm/manifestservice/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/manifestservice/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/manifestservice/templates/external-secret.yaml b/helm/manifestservice/templates/external-secret.yaml new file mode 100644 index 00000000..51d31656 --- /dev/null +++ b/helm/manifestservice/templates/external-secret.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: manifestservice-g3auto +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: manifestservice-g3auto + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "manifestservice-g3auto" .}} +{{- end }} \ No newline at end of file diff --git a/helm/manifestservice/templates/metadataservice-creds.yaml b/helm/manifestservice/templates/manifestservice-creds.yaml similarity index 99% rename from helm/manifestservice/templates/metadataservice-creds.yaml rename to helm/manifestservice/templates/manifestservice-creds.yaml index 22dd070a..5194515c 100644 --- a/helm/manifestservice/templates/metadataservice-creds.yaml +++ b/helm/manifestservice/templates/manifestservice-creds.yaml @@ -12,4 +12,3 @@ stringData: "aws_secret_access_key": "{{ .Values.manifestserviceG3auto.awssecretkey }}", "prefix": "{{ .Values.manifestserviceG3auto.prefix }}" } - diff --git a/helm/manifestservice/values.yaml b/helm/manifestservice/values.yaml index 2607c9a7..4d1d0f67 100644 --- a/helm/manifestservice/values.yaml +++ b/helm/manifestservice/values.yaml @@ -4,6 +4,14 @@ # -- (map) Global configuration options. global: + # -- (map) AWS configuration + aws: + # -- (bool) Set to true if deploying to AWS. Controls ingress annotations. + enabled: false + # -- (string) Credentials for AWS stuff. + awsAccessKeyId: + # -- (string) Credentials for AWS stuff. + awsSecretAccessKey: # -- (string) Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. environment: default # -- (bool) Whether Datadog is enabled. @@ -12,6 +20,23 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any manifestservice secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "manifestservice-g3auto" + manifestserviceG3auto: +# -- (map) Secret information for External Secrets. +secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID. Overrides global key. + awsSecretAccessKey: # -- (int) Number of old revisions to retain revisionHistoryLimit: 2 diff --git a/helm/metadata/Chart.yaml b/helm/metadata/Chart.yaml index 718ca364..5a079f18 100644 --- a/helm/metadata/Chart.yaml +++ b/helm/metadata/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.8 +version: 0.1.9 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/metadata/README.md b/helm/metadata/README.md index aa2422ea..83cfac87 100644 --- a/helm/metadata/README.md +++ b/helm/metadata/README.md @@ -1,6 +1,6 @@ # metadata -![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.9](https://img.shields.io/badge/Version-0.1.9-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Metadata Service @@ -38,7 +38,9 @@ A Helm chart for gen3 Metadata Service | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | debug | bool | `false` | | | esEndpoint | string | `"elasticsearch:9200"` | Elasticsearch endpoint. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | +| externalSecrets | map | `{"metadataSmDbcreds":null}` | External Secrets settings. | +| externalSecrets.metadataSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -48,6 +50,9 @@ A Helm chart for gen3 Metadata Service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any metadata secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | @@ -96,6 +101,9 @@ A Helm chart for gen3 Metadata Service | resources.requests.cpu | string | `0.1` | The amount of CPU requested | | resources.requests.memory | string | `"12Mi"` | The amount of memory requested | | revisionHistoryLimit | int | `2` | Number of old revisions to retain | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information to access the db restore job S3 bucket. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"port":[{"name":"http","port":80,"protocol":"TCP","targetPort":80}],"type":"ClusterIP"}` | Kubernetes service information. | | service.port | int | `[{"name":"http","port":80,"protocol":"TCP","targetPort":80}]` | The port number that the service exposes. | diff --git a/helm/metadata/templates/_helpers.tpl b/helm/metadata/templates/_helpers.tpl index f8424983..ef1edcef 100644 --- a/helm/metadata/templates/_helpers.tpl +++ b/helm/metadata/templates/_helpers.tpl @@ -77,3 +77,25 @@ Create the name of the service account to use {{- default .Values.postgres.password }} {{- end }} {{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} + {{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "metadata-sm-dbcreds" -}} +{{- if .Values.externalSecrets.metadataSmDbcreds }} + {{- default .Values.externalSecrets.metadataSmDbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} diff --git a/helm/metadata/templates/aws-config.yaml b/helm/metadata/templates/aws-config.yaml new file mode 100644 index 00000000..4723e6b3 --- /dev/null +++ b/helm/metadata/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end }} \ No newline at end of file diff --git a/helm/metadata/templates/cluster-secret-store.yaml b/helm/metadata/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/metadata/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/metadata/templates/external-secret.yaml b/helm/metadata/templates/external-secret.yaml new file mode 100644 index 00000000..179c5f77 --- /dev/null +++ b/helm/metadata/templates/external-secret.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "metadata-sm-dbcreds" .}} +{{- end }} \ No newline at end of file diff --git a/helm/metadata/values.yaml b/helm/metadata/values.yaml index baaa5cb6..cfdb6fd0 100644 --- a/helm/metadata/values.yaml +++ b/helm/metadata/values.yaml @@ -56,6 +56,23 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any metadata secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + metadataSmDbcreds: +# -- (map) Secret information to access the db restore job S3 bucket. +secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID. Overrides global key. + awsSecretAccessKey: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: diff --git a/helm/peregrine/Chart.yaml b/helm/peregrine/Chart.yaml index cfdfe6e3..ada8310a 100644 --- a/helm/peregrine/Chart.yaml +++ b/helm/peregrine/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.9 +version: 0.1.10 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/peregrine/README.md b/helm/peregrine/README.md index 838e811c..1116148b 100644 --- a/helm/peregrine/README.md +++ b/helm/peregrine/README.md @@ -1,6 +1,6 @@ # peregrine -![Version: 0.1.9](https://img.shields.io/badge/Version-0.1.9-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2023.01](https://img.shields.io/badge/AppVersion-2023.01-informational?style=flat-square) +![Version: 0.1.10](https://img.shields.io/badge/Version-0.1.10-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2023.01](https://img.shields.io/badge/AppVersion-2023.01-informational?style=flat-square) A Helm chart for gen3 Peregrine service @@ -28,8 +28,10 @@ A Helm chart for gen3 Peregrine service | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `nil` | Environment variables to pass to the container | +| externalSecrets | map | `{"peregrineSmDbcreds":null}` | External Secrets settings. | +| externalSecrets.peregrineSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -39,6 +41,9 @@ A Helm chart for gen3 Peregrine service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any peregrine secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | @@ -82,6 +87,9 @@ A Helm chart for gen3 Peregrine service | resources.requests | map | `{"cpu":0.1,"memory":"12Mi"}` | The amount of resources that the container requests | | resources.requests.cpu | string | `0.1` | The amount of CPU requested | | resources.requests.memory | string | `"12Mi"` | The amount of memory requested | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information for External Secrets. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | securityContext | map | `{}` | Security context for the containers in the pod | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"port":80,"type":"ClusterIP"}` | Kubernetes service information. | diff --git a/helm/peregrine/templates/_helpers.tpl b/helm/peregrine/templates/_helpers.tpl index 1674a02f..68bb8634 100644 --- a/helm/peregrine/templates/_helpers.tpl +++ b/helm/peregrine/templates/_helpers.tpl @@ -90,4 +90,26 @@ Define dictionaryUrl {{- else}} {{- .Values.dictionaryUrl }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} + {{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "peregrine-sm-dbcreds" -}} +{{- if .Values.externalSecrets.peregrineSmDbcreds }} + {{- default .Values.externalSecrets.peregrineSmDbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} diff --git a/helm/peregrine/templates/aws-config.yaml b/helm/peregrine/templates/aws-config.yaml new file mode 100644 index 00000000..398770d3 --- /dev/null +++ b/helm/peregrine/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/peregrine/templates/cluster-secret-store.yaml b/helm/peregrine/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/peregrine/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/peregrine/templates/external-secret.yaml b/helm/peregrine/templates/external-secret.yaml new file mode 100644 index 00000000..a25b7a45 --- /dev/null +++ b/helm/peregrine/templates/external-secret.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "peregrine-sm-dbcreds" .}} +{{- end }} \ No newline at end of file diff --git a/helm/peregrine/values.yaml b/helm/peregrine/values.yaml index 3335f8e3..fe92f044 100644 --- a/helm/peregrine/values.yaml +++ b/helm/peregrine/values.yaml @@ -53,6 +53,24 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any peregrine secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + peregrineSmDbcreds: +# -- (map) Secret information for External Secrets. +secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID. Overrides global key. + awsSecretAccessKey: + # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: diff --git a/helm/requestor/Chart.yaml b/helm/requestor/Chart.yaml index 4e59fb2a..2c4a8c43 100644 --- a/helm/requestor/Chart.yaml +++ b/helm/requestor/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.8 +version: 0.1.9 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/requestor/README.md b/helm/requestor/README.md index 5e7666f8..4b7c0cc2 100644 --- a/helm/requestor/README.md +++ b/helm/requestor/README.md @@ -1,6 +1,6 @@ # requestor -![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.9](https://img.shields.io/badge/Version-0.1.9-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Requestor Service @@ -36,7 +36,9 @@ A Helm chart for gen3 Requestor Service | datadogLogsInjection | bool | `true` | If enabled, the Datadog Agent will automatically inject Datadog-specific metadata into your application logs. | | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | -| global | map | `{"addDbgap":false,"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"onlyDbgap":false,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","slack_send_dbgap":false,"slack_webhook":"None","syncFromDbgap":false,"tierAccessLevel":"libre","userYamlS3Path":"s3://cdis-gen3-users/helm-test/user.yaml","usersync":false}` | Global configuration options. | +| externalSecrets | map | `{"requestorSmDbcreds":null}` | External Secrets settings. | +| externalSecrets.requestorSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | +| global | map | `{"addDbgap":false,"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"onlyDbgap":false,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","slack_send_dbgap":false,"slack_webhook":"None","syncFromDbgap":false,"tierAccessLevel":"libre","userYamlS3Path":"s3://cdis-gen3-users/helm-test/user.yaml","usersync":false}` | Global configuration options. | | global.addDbgap | bool | `false` | Force attempting a dbgap sync if "true", falls back on user.yaml | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | @@ -47,6 +49,9 @@ A Helm chart for gen3 Requestor Service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any requestor secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | @@ -101,6 +106,9 @@ A Helm chart for gen3 Requestor Service | resources.requests.cpu | string | `0.1` | The amount of CPU requested | | resources.requests.memory | string | `"12Mi"` | The amount of memory requested | | revisionHistoryLimit | int | `2` | Number of old revisions to retain | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null}` | Secret information for External Secrets. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"port":[{"name":"http","port":80,"protocol":"TCP","targetPort":80}],"type":"ClusterIP"}` | Kubernetes service information. | | service.port | int | `[{"name":"http","port":80,"protocol":"TCP","targetPort":80}]` | The port number that the service exposes. | diff --git a/helm/requestor/templates/_helpers.tpl b/helm/requestor/templates/_helpers.tpl index 899b723c..3af66e0b 100644 --- a/helm/requestor/templates/_helpers.tpl +++ b/helm/requestor/templates/_helpers.tpl @@ -77,4 +77,26 @@ Create the name of the service account to use {{- else }} {{- default .Values.secrets.password }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} + {{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "requestor-sm-dbcreds" -}} +{{- if .Values.externalSecrets.requestorSmDbcreds }} + {{- default .Values.externalSecrets.requestorSmDbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} diff --git a/helm/requestor/templates/aws-config.yaml b/helm/requestor/templates/aws-config.yaml new file mode 100644 index 00000000..398770d3 --- /dev/null +++ b/helm/requestor/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/requestor/templates/cluster-secret-store.yaml b/helm/requestor/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/requestor/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/requestor/templates/external-secret.yaml b/helm/requestor/templates/external-secret.yaml new file mode 100644 index 00000000..9476e59b --- /dev/null +++ b/helm/requestor/templates/external-secret.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "requestor-sm-dbcreds" .}} +{{- end }} \ No newline at end of file diff --git a/helm/requestor/values.yaml b/helm/requestor/values.yaml index 437ffac6..20ade152 100644 --- a/helm/requestor/values.yaml +++ b/helm/requestor/values.yaml @@ -70,6 +70,23 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any requestor secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + requestorSmDbcreds: +# -- (map) Secret information for External Secrets. +secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID. Overrides global key. + awsSecretAccessKey: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: diff --git a/helm/sheepdog/Chart.yaml b/helm/sheepdog/Chart.yaml index cb5745a2..7a68d313 100644 --- a/helm/sheepdog/Chart.yaml +++ b/helm/sheepdog/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.10 +version: 0.1.11 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/sheepdog/README.md b/helm/sheepdog/README.md index e2a57245..026324b0 100644 --- a/helm/sheepdog/README.md +++ b/helm/sheepdog/README.md @@ -1,6 +1,6 @@ # sheepdog -![Version: 0.1.10](https://img.shields.io/badge/Version-0.1.10-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.11](https://img.shields.io/badge/Version-0.1.11-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Sheepdog Service @@ -37,8 +37,10 @@ A Helm chart for gen3 Sheepdog Service | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | +| externalSecrets | map | `{"sheepdogSmDbcreds":null}` | External Secrets settings. | +| externalSecrets.sheepdogSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fenceUrl | string | `"http://fence-service"` | URL for the fence service | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -48,6 +50,9 @@ A Helm chart for gen3 Sheepdog Service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any sheepdog secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | @@ -93,7 +98,9 @@ A Helm chart for gen3 Sheepdog Service | resources.requests.cpu | string | `0.3` | The amount of CPU requested | | resources.requests.memory | string | `"12Mi"` | The amount of memory requested | | revisionHistoryLimit | int | `2` | Number of old revisions to retain | -| secrets | map | `{"fence":{"database":"fence","host":"postgres-postgresql.postgres.svc.cluster.local","password":"postgres","user":"postgres"},"gdcapi":{"secretKey":null},"indexd":{"password":"postgres"},"sheepdog":{"database":"sheepdog","host":"postgres-postgresql.postgres.svc.cluster.local","password":"postgres","user":"postgres"}}` | Values for sheepdog secret. | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"fence":{"database":"fence","host":"postgres-postgresql.postgres.svc.cluster.local","password":"postgres","user":"postgres"},"gdcapi":{"secretKey":null},"indexd":{"password":"postgres"},"sheepdog":{"database":"sheepdog","host":"postgres-postgresql.postgres.svc.cluster.local","password":"postgres","user":"postgres"}}` | Values for sheepdog secret. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID to access the db restore job S3 bucket. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID to access the db restore job S3 bucket. Overrides global key. | | secrets.fence | map | `{"database":"fence","host":"postgres-postgresql.postgres.svc.cluster.local","password":"postgres","user":"postgres"}` | Values for sheepdog's access to the fence database. | | secrets.fence.database | string | `"fence"` | Database name for fence's db. | | secrets.fence.host | string | `"postgres-postgresql.postgres.svc.cluster.local"` | Host for fence's db. | diff --git a/helm/sheepdog/templates/_helpers.tpl b/helm/sheepdog/templates/_helpers.tpl index 1c935c37..669071f7 100644 --- a/helm/sheepdog/templates/_helpers.tpl +++ b/helm/sheepdog/templates/_helpers.tpl @@ -100,4 +100,26 @@ Define dictionaryUrl {{- else}} {{- .Values.dictionaryUrl }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} + {{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "sheepdog-sm-dbcreds" -}} +{{- if .Values.externalSecrets.sheepdogSmDbcreds }} + {{- default .Values.externalSecrets.sheepdogSmDbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} diff --git a/helm/sheepdog/templates/aws-config.yaml b/helm/sheepdog/templates/aws-config.yaml new file mode 100644 index 00000000..745635c1 --- /dev/null +++ b/helm/sheepdog/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.dbRestore) (.Values.global.externalSecrets.deploy) }} +{{ include "common.awsconfig" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/sheepdog/templates/cluster-secret-store.yaml b/helm/sheepdog/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/sheepdog/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/sheepdog/templates/external-secrets.yaml b/helm/sheepdog/templates/external-secrets.yaml new file mode 100644 index 00000000..afd441e2 --- /dev/null +++ b/helm/sheepdog/templates/external-secrets.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "sheepdog-sm-dbcreds" .}} +{{- end }} \ No newline at end of file diff --git a/helm/sheepdog/values.yaml b/helm/sheepdog/values.yaml index 941c33c6..8a94905e 100644 --- a/helm/sheepdog/values.yaml +++ b/helm/sheepdog/values.yaml @@ -56,6 +56,17 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any sheepdog secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + sheepdogSmDbcreds: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: @@ -227,6 +238,10 @@ secrets: indexd: # -- (string) Password to indexd's db. password: postgres + # -- (str) AWS access key ID to access the db restore job S3 bucket. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID to access the db restore job S3 bucket. Overrides global key. + awsSecretAccessKey: # Values to determine the labels that are used for the deployment, pod, etc. # -- (string) Valid options are "production" or "dev". If invalid option is set- the value will default to "dev". diff --git a/helm/wts/Chart.yaml b/helm/wts/Chart.yaml index a1c29c60..31869111 100644 --- a/helm/wts/Chart.yaml +++ b/helm/wts/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.10 +version: 0.1.11 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/wts/README.md b/helm/wts/README.md index 7644f5fc..a52f93a7 100644 --- a/helm/wts/README.md +++ b/helm/wts/README.md @@ -1,6 +1,6 @@ # wts -![Version: 0.1.10](https://img.shields.io/badge/Version-0.1.10-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.11](https://img.shields.io/badge/Version-0.1.11-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 workspace token service @@ -26,8 +26,10 @@ A Helm chart for gen3 workspace token service | datadogLogsInjection | bool | `true` | If enabled, the Datadog Agent will automatically inject Datadog-specific metadata into your application logs. | | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | +| externalSecrets | map | `{"wtsSmDbcreds":null}` | External Secrets settings. | +| externalSecrets.wtsSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -37,6 +39,9 @@ A Helm chart for gen3 workspace token service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any wts secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | @@ -86,7 +91,9 @@ A Helm chart for gen3 workspace token service | resources.requests.cpu | string | `0.2` | The amount of CPU requested | | resources.requests.memory | string | `"120Mi"` | The amount of memory requested | | roleName | string | `"workspace-token-service"` | Name of the role to be used for the role binding. | -| secrets | map | `{"external_oidc":null}` | Values for wts secret. | +| secrets | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"external_oidc":null}` | Values for wts secret and keys for External Secrets. | +| secrets.awsAccessKeyId | str | `nil` | AWS access key ID. Overrides global key. | +| secrets.awsSecretAccessKey | str | `nil` | AWS secret access key ID. Overrides global key. | | securityContext | map | `{}` | Security context for the containers in the pod | | selectorLabels | map | `nil` | Will completely override the selectorLabels defined in the common chart's _label_setup.tpl | | service | map | `{"httpPort":80,"httpsPort":443,"type":"ClusterIP"}` | Configuration for the service | diff --git a/helm/wts/templates/_helpers.tpl b/helm/wts/templates/_helpers.tpl index f8cebb83..a4b820b5 100644 --- a/helm/wts/templates/_helpers.tpl +++ b/helm/wts/templates/_helpers.tpl @@ -78,4 +78,26 @@ Create the name of the service account to use {{- else }} {{- default .Values.postgres.password }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "cluster-secret-store" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} + {{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} + +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "wts-sm-dbcreds" -}} +{{- if .Values.externalSecrets.wtsSmDbcreds }} + {{- default .Values.externalSecrets.wtsSmDbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} diff --git a/helm/wts/templates/aws-config.yaml b/helm/wts/templates/aws-config.yaml new file mode 100644 index 00000000..398770d3 --- /dev/null +++ b/helm/wts/templates/aws-config.yaml @@ -0,0 +1,3 @@ +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} +{{ include "common.awsconfig" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/wts/templates/cluster-secret-store.yaml b/helm/wts/templates/cluster-secret-store.yaml new file mode 100644 index 00000000..8c1c7717 --- /dev/null +++ b/helm/wts/templates/cluster-secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separate }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/wts/templates/external-secret.yaml b/helm/wts/templates/external-secret.yaml new file mode 100644 index 00000000..d18abd46 --- /dev/null +++ b/helm/wts/templates/external-secret.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + #name of secret in secrets manager + key: {{include "wts-sm-dbcreds" .}} +{{- end }} \ No newline at end of file diff --git a/helm/wts/values.yaml b/helm/wts/values.yaml index 2eb8c2d1..e4ec06f6 100644 --- a/helm/wts/values.yaml +++ b/helm/wts/values.yaml @@ -56,6 +56,17 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + # -- (map) External Secrets settings. + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any wts secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false + +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + wtsSmDbcreds: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: @@ -185,8 +196,12 @@ affinity: {} # -- (string) Name of the role to be used for the role binding. roleName: workspace-token-service -# -- (map) Values for wts secret. +# -- (map) Values for wts secret and keys for External Secrets. secrets: + # -- (str) AWS access key ID. Overrides global key. + awsAccessKeyId: + # -- (str) AWS secret access key ID. Overrides global key. + awsSecretAccessKey: external_oidc: # - base_url: # oidc_client_id: From a7f368d9b319193d3f364c8f8b7cc9830f4d0db6 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 3 Aug 2023 15:56:21 -0600 Subject: [PATCH 02/60] updating dependency versions --- .secrets.baseline | 36 ++++++++++++++--------------- helm/ambassador/Chart.yaml | 4 ++-- helm/ambassador/README.md | 4 ++-- helm/arborist/Chart.yaml | 2 +- helm/arborist/README.md | 2 +- helm/argo-wrapper/Chart.yaml | 4 ++-- helm/argo-wrapper/README.md | 4 ++-- helm/audit/Chart.yaml | 2 +- helm/audit/README.md | 2 +- helm/aws-es-proxy/Chart.yaml | 2 +- helm/aws-es-proxy/README.md | 2 +- helm/dicom-server/Chart.yaml | 4 ++-- helm/dicom-server/README.md | 4 ++-- helm/dicom-viewer/Chart.yaml | 4 ++-- helm/dicom-viewer/README.md | 4 ++-- helm/elasticsearch/Chart.yaml | 4 ++-- helm/elasticsearch/README.md | 4 ++-- helm/fence/Chart.yaml | 2 +- helm/fence/README.md | 2 +- helm/gen3/Chart.yaml | 40 ++++++++++++++++---------------- helm/gen3/README.md | 41 ++++++++++++++++----------------- helm/guppy/Chart.yaml | 2 +- helm/guppy/README.md | 2 +- helm/hatchery/Chart.yaml | 4 ++-- helm/hatchery/README.md | 4 ++-- helm/indexd/Chart.yaml | 2 +- helm/indexd/README.md | 2 +- helm/manifestservice/Chart.yaml | 2 +- helm/manifestservice/README.md | 2 +- helm/metadata/Chart.yaml | 2 +- helm/metadata/README.md | 2 +- helm/peregrine/Chart.yaml | 2 +- helm/peregrine/README.md | 2 +- helm/pidgin/Chart.yaml | 4 ++-- helm/pidgin/README.md | 4 ++-- helm/portal/Chart.yaml | 4 ++-- helm/portal/README.md | 4 ++-- helm/requestor/Chart.yaml | 2 +- helm/requestor/README.md | 2 +- helm/revproxy/Chart.yaml | 4 ++-- helm/revproxy/README.md | 4 ++-- helm/sheepdog/Chart.yaml | 2 +- helm/sheepdog/README.md | 2 +- helm/sower/Chart.yaml | 2 +- helm/sower/README.md | 2 +- helm/ssjdispatcher/Chart.yaml | 4 ++-- helm/ssjdispatcher/README.md | 4 ++-- helm/wts/Chart.yaml | 2 +- helm/wts/README.md | 2 +- 49 files changed, 124 insertions(+), 125 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 4a5dde43..32f7c4a2 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2023-08-03T21:28:39Z", + "generated_at": "2023-08-03T21:53:32Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -131,28 +131,28 @@ "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", "is_secret": false, "is_verified": false, - "line_number": 32, + "line_number": 34, "type": "Secret Keyword" }, { "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", "is_secret": false, "is_verified": false, - "line_number": 45, + "line_number": 54, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 47, + "line_number": 56, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 65, + "line_number": 74, "type": "Secret Keyword" } ], @@ -161,28 +161,28 @@ "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", "is_secret": false, "is_verified": false, - "line_number": 40, + "line_number": 43, "type": "Secret Keyword" }, { "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", "is_secret": false, "is_verified": false, - "line_number": 53, + "line_number": 63, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 55, + "line_number": 65, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 75, + "line_number": 85, "type": "Secret Keyword" } ], @@ -530,35 +530,35 @@ "hashed_secret": "4e7b6794afbe3027589b92744144f18a3920b115", "is_secret": false, "is_verified": false, - "line_number": 32, + "line_number": 34, "type": "Secret Keyword" }, { "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", "is_secret": false, "is_verified": false, - "line_number": 49, + "line_number": 54, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 51, + "line_number": 56, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 67, + "line_number": 72, "type": "Secret Keyword" }, { "hashed_secret": "7d4e263f1ae83868444f5327219830493a7d1486", "is_secret": false, "is_verified": false, - "line_number": 96, + "line_number": 104, "type": "Secret Keyword" } ], @@ -886,28 +886,28 @@ "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", "is_secret": false, "is_verified": false, - "line_number": 30, + "line_number": 32, "type": "Secret Keyword" }, { "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", "is_secret": false, "is_verified": false, - "line_number": 47, + "line_number": 52, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 49, + "line_number": 54, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 70, + "line_number": 75, "type": "Secret Keyword" } ], diff --git a/helm/ambassador/Chart.yaml b/helm/ambassador/Chart.yaml index 5acd83d5..b4e745d5 100644 --- a/helm/ambassador/Chart.yaml +++ b/helm/ambassador/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.8 +version: 0.1.9 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "1.4.2" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/ambassador/README.md b/helm/ambassador/README.md index 2a56dd52..06e4b0e2 100644 --- a/helm/ambassador/README.md +++ b/helm/ambassador/README.md @@ -1,6 +1,6 @@ # ambassador -![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.4.2](https://img.shields.io/badge/AppVersion-1.4.2-informational?style=flat-square) +![Version: 0.1.9](https://img.shields.io/badge/Version-0.1.9-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.4.2](https://img.shields.io/badge/AppVersion-1.4.2-informational?style=flat-square) A Helm chart for deploying ambassador for gen3 @@ -8,7 +8,7 @@ A Helm chart for deploying ambassador for gen3 | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/arborist/Chart.yaml b/helm/arborist/Chart.yaml index 25247023..3ef314d6 100644 --- a/helm/arborist/Chart.yaml +++ b/helm/arborist/Chart.yaml @@ -25,7 +25,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/arborist/README.md b/helm/arborist/README.md index 954eaa83..7df700a8 100644 --- a/helm/arborist/README.md +++ b/helm/arborist/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 arborist | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/argo-wrapper/Chart.yaml b/helm/argo-wrapper/Chart.yaml index dbad7182..5d320e9d 100644 --- a/helm/argo-wrapper/Chart.yaml +++ b/helm/argo-wrapper/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.4 +version: 0.1.5 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/argo-wrapper/README.md b/helm/argo-wrapper/README.md index 8ca7a922..b5f7b3a1 100644 --- a/helm/argo-wrapper/README.md +++ b/helm/argo-wrapper/README.md @@ -1,6 +1,6 @@ # argo-wrapper -![Version: 0.1.4](https://img.shields.io/badge/Version-0.1.4-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.5](https://img.shields.io/badge/Version-0.1.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Argo Wrapper Service @@ -8,7 +8,7 @@ A Helm chart for gen3 Argo Wrapper Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/audit/Chart.yaml b/helm/audit/Chart.yaml index 4201f353..fbd974a8 100644 --- a/helm/audit/Chart.yaml +++ b/helm/audit/Chart.yaml @@ -24,7 +24,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/audit/README.md b/helm/audit/README.md index 9398de52..49ec0eca 100644 --- a/helm/audit/README.md +++ b/helm/audit/README.md @@ -8,7 +8,7 @@ A Helm chart for Kubernetes | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/aws-es-proxy/Chart.yaml b/helm/aws-es-proxy/Chart.yaml index dc35848c..80466f8b 100644 --- a/helm/aws-es-proxy/Chart.yaml +++ b/helm/aws-es-proxy/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/aws-es-proxy/README.md b/helm/aws-es-proxy/README.md index 161c15f2..7ddd2bfc 100644 --- a/helm/aws-es-proxy/README.md +++ b/helm/aws-es-proxy/README.md @@ -8,7 +8,7 @@ A Helm chart for AWS ES Proxy Service for gen3 | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/dicom-server/Chart.yaml b/helm/dicom-server/Chart.yaml index f8777d39..5605eab7 100644 --- a/helm/dicom-server/Chart.yaml +++ b/helm/dicom-server/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.5 +version: 0.1.6 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/dicom-server/README.md b/helm/dicom-server/README.md index 6d24ac03..fd8c52f9 100644 --- a/helm/dicom-server/README.md +++ b/helm/dicom-server/README.md @@ -1,6 +1,6 @@ # dicom-server -![Version: 0.1.5](https://img.shields.io/badge/Version-0.1.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Dicom Server @@ -8,7 +8,7 @@ A Helm chart for gen3 Dicom Server | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/dicom-viewer/Chart.yaml b/helm/dicom-viewer/Chart.yaml index bdff7a6a..dd84c125 100644 --- a/helm/dicom-viewer/Chart.yaml +++ b/helm/dicom-viewer/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.5 +version: 0.1.6 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/dicom-viewer/README.md b/helm/dicom-viewer/README.md index 3ea1757e..78ea3e63 100644 --- a/helm/dicom-viewer/README.md +++ b/helm/dicom-viewer/README.md @@ -1,6 +1,6 @@ # dicom-viewer -![Version: 0.1.5](https://img.shields.io/badge/Version-0.1.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Dicom Viewer @@ -8,7 +8,7 @@ A Helm chart for gen3 Dicom Viewer | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/elasticsearch/Chart.yaml b/helm/elasticsearch/Chart.yaml index 1720df09..a1754093 100644 --- a/helm/elasticsearch/Chart.yaml +++ b/helm/elasticsearch/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.5 +version: 0.1.6 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "1.16.0" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/elasticsearch/README.md b/helm/elasticsearch/README.md index c9852ebc..132f8fa7 100644 --- a/helm/elasticsearch/README.md +++ b/helm/elasticsearch/README.md @@ -1,6 +1,6 @@ # elasticsearch -![Version: 0.1.5](https://img.shields.io/badge/Version-0.1.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.16.0](https://img.shields.io/badge/AppVersion-1.16.0-informational?style=flat-square) +![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.16.0](https://img.shields.io/badge/AppVersion-1.16.0-informational?style=flat-square) A Helm chart for Kubernetes @@ -8,7 +8,7 @@ A Helm chart for Kubernetes | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/fence/Chart.yaml b/helm/fence/Chart.yaml index 36d58d86..d3203de8 100644 --- a/helm/fence/Chart.yaml +++ b/helm/fence/Chart.yaml @@ -24,7 +24,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/fence/README.md b/helm/fence/README.md index 013a4673..af3a93ac 100644 --- a/helm/fence/README.md +++ b/helm/fence/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Fence | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/gen3/Chart.yaml b/helm/gen3/Chart.yaml index 1d602327..9c567bb5 100644 --- a/helm/gen3/Chart.yaml +++ b/helm/gen3/Chart.yaml @@ -5,78 +5,78 @@ description: Helm chart to deploy Gen3 Data Commons # Dependancies dependencies: - name: ambassador - version: "0.1.8" + version: "0.1.9" repository: "file://../ambassador" condition: ambassador.enabled - name: arborist - version: "0.1.8" + version: "0.1.9" repository: "file://../arborist" condition: arborist.enabled - name: argo-wrapper - version: "0.1.4" + version: "0.1.5" repository: "file://../argo-wrapper" condition: argo-wrapper.enabled - name: audit - version: "0.1.9" + version: "0.1.10" repository: "file://../audit" condition: audit.enabled - name: aws-es-proxy - version: "0.1.6" + version: "0.1.7" repository: "file://../aws-es-proxy" condition: aws-es-proxy.enabled - name: common - version: "0.1.7" + version: "0.1.8" repository: file://../common - name: fence - version: "0.1.13" + version: "0.1.14" repository: "file://../fence" condition: fence.enabled - name: guppy - version: "0.1.8" + version: "0.1.9" repository: "file://../guppy" condition: guppy.enabled - name: hatchery - version: "0.1.6" + version: "0.1.7" repository: "file://../hatchery" condition: hatchery.enabled - name: indexd - version: "0.1.10" + version: "0.1.11" repository: "file://../indexd" condition: indexd.enabled - name: manifestservice - version: "0.1.10" + version: "0.1.11" repository: "file://../manifestservice" condition: manifestservice.enabled - name: metadata - version: "0.1.8" + version: "0.1.9" repository: "file://../metadata" condition: metadata.enabled - name: peregrine - version: "0.1.9" + version: "0.1.10" repository: "file://../peregrine" condition: peregrine.enabled - name: pidgin - version: "0.1.7" + version: "0.1.8" repository: "file://../pidgin" condition: pidgin.enabled - name: portal - version: "0.1.7" + version: "0.1.8" repository: "file://../portal" condition: portal.enabled - name: requestor - version: "0.1.8" + version: "0.1.9" repository: "file://../requestor" condition: requestor.enabled - name: revproxy - version: "0.1.10" + version: "0.1.11" repository: "file://../revproxy" condition: revproxy.enabled - name: sheepdog - version: "0.1.10" + version: "0.1.11" repository: "file://../sheepdog" condition: sheepdog.enabled - name: ssjdispatcher - version: "0.1.6" + version: "0.1.7" repository: "file://../ssjdispatcher" condition: ssjdispatcher.enabled - name: sower @@ -84,7 +84,7 @@ dependencies: condition: sower.enabled repository: "file://../sower" - name: wts - version: "0.1.10" + version: "0.1.11" repository: "file://../wts" condition: wts.enabled diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 948fe7f0..0f574a9d 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -18,28 +18,27 @@ Helm chart to deploy Gen3 Data Commons | Repository | Name | Version | |------------|------|---------| -| file://../ambassador | ambassador | 0.1.8 | -| file://../arborist | arborist | 0.1.8 | -| file://../argo-wrapper | argo-wrapper | 0.1.4 | -| file://../audit | audit | 0.1.9 | -| file://../aws-es-proxy | aws-es-proxy | 0.1.6 | -| file://../common | common | 0.1.7 | +| file://../ambassador | ambassador | 0.1.9 | +| file://../arborist | arborist | 0.1.9 | +| file://../argo-wrapper | argo-wrapper | 0.1.5 | +| file://../audit | audit | 0.1.10 | +| file://../aws-es-proxy | aws-es-proxy | 0.1.7 | +| file://../common | common | 0.1.8 | | file://../elasticsearch | elasticsearch | 0.1.5 | -| file://../fence | fence | 0.1.13 | -| file://../guppy | guppy | 0.1.8 | -| file://../hatchery | hatchery | 0.1.6 | -| file://../indexd | indexd | 0.1.10 | -| file://../manifestservice | manifestservice | 0.1.10 | -| file://../metadata | metadata | 0.1.8 | -| file://../peregrine | peregrine | 0.1.9 | -| file://../pidgin | pidgin | 0.1.7 | -| file://../portal | portal | 0.1.7 | -| file://../requestor | requestor | 0.1.8 | -| file://../revproxy | revproxy | 0.1.10 | -| file://../sheepdog | sheepdog | 0.1.10 | -| file://../sower | sower | 0.1.6 | -| file://../ssjdispatcher | ssjdispatcher | 0.1.6 | -| file://../wts | wts | 0.1.10 | +| file://../fence | fence | 0.1.14 | +| file://../guppy | guppy | 0.1.9 | +| file://../hatchery | hatchery | 0.1.7 | +| file://../indexd | indexd | 0.1.11 | +| file://../manifestservice | manifestservice | 0.1.11 | +| file://../metadata | metadata | 0.1.9 | +| file://../peregrine | peregrine | 0.1.10 | +| file://../pidgin | pidgin | 0.1.8 | +| file://../portal | portal | 0.1.8 | +| file://../requestor | requestor | 0.1.9 | +| file://../revproxy | revproxy | 0.1.11 | +| file://../sheepdog | sheepdog | 0.1.11 | +| file://../ssjdispatcher | ssjdispatcher | 0.1.7 | +| file://../wts | wts | 0.1.11 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/guppy/Chart.yaml b/helm/guppy/Chart.yaml index 976494e2..8243c558 100644 --- a/helm/guppy/Chart.yaml +++ b/helm/guppy/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/guppy/README.md b/helm/guppy/README.md index 911be38f..f8c99a11 100644 --- a/helm/guppy/README.md +++ b/helm/guppy/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Guppy Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/hatchery/Chart.yaml b/helm/hatchery/Chart.yaml index 94913173..bb311c95 100644 --- a/helm/hatchery/Chart.yaml +++ b/helm/hatchery/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.6 +version: 0.1.7 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/hatchery/README.md b/helm/hatchery/README.md index 211e61f4..4e7bfe3c 100644 --- a/helm/hatchery/README.md +++ b/helm/hatchery/README.md @@ -1,6 +1,6 @@ # hatchery -![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.7](https://img.shields.io/badge/Version-0.1.7-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Hatchery @@ -8,7 +8,7 @@ A Helm chart for gen3 Hatchery | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/indexd/Chart.yaml b/helm/indexd/Chart.yaml index 8890042a..c7b2b223 100644 --- a/helm/indexd/Chart.yaml +++ b/helm/indexd/Chart.yaml @@ -26,7 +26,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/indexd/README.md b/helm/indexd/README.md index eaa6a92d..e8108d81 100644 --- a/helm/indexd/README.md +++ b/helm/indexd/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 indexd | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/manifestservice/Chart.yaml b/helm/manifestservice/Chart.yaml index e01a6ba2..3b5eee3a 100644 --- a/helm/manifestservice/Chart.yaml +++ b/helm/manifestservice/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/manifestservice/README.md b/helm/manifestservice/README.md index 7969f749..ad10c8c8 100644 --- a/helm/manifestservice/README.md +++ b/helm/manifestservice/README.md @@ -8,7 +8,7 @@ A Helm chart for Kubernetes | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/metadata/Chart.yaml b/helm/metadata/Chart.yaml index 5a079f18..1b1a0f07 100644 --- a/helm/metadata/Chart.yaml +++ b/helm/metadata/Chart.yaml @@ -25,7 +25,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/metadata/README.md b/helm/metadata/README.md index 83cfac87..8e115391 100644 --- a/helm/metadata/README.md +++ b/helm/metadata/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Metadata Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/peregrine/Chart.yaml b/helm/peregrine/Chart.yaml index ada8310a..6fea8732 100644 --- a/helm/peregrine/Chart.yaml +++ b/helm/peregrine/Chart.yaml @@ -26,7 +26,7 @@ appVersion: "2023.01" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/peregrine/README.md b/helm/peregrine/README.md index 1116148b..55b8da06 100644 --- a/helm/peregrine/README.md +++ b/helm/peregrine/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Peregrine service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/pidgin/Chart.yaml b/helm/pidgin/Chart.yaml index 831c01ac..c871f126 100644 --- a/helm/pidgin/Chart.yaml +++ b/helm/pidgin/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.7 +version: 0.1.8 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/pidgin/README.md b/helm/pidgin/README.md index 5c4bcdb9..72b5f9bc 100644 --- a/helm/pidgin/README.md +++ b/helm/pidgin/README.md @@ -1,6 +1,6 @@ # pidgin -![Version: 0.1.7](https://img.shields.io/badge/Version-0.1.7-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 Pidgin Service @@ -8,7 +8,7 @@ A Helm chart for gen3 Pidgin Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/portal/Chart.yaml b/helm/portal/Chart.yaml index 61f4b9ca..1a992152 100644 --- a/helm/portal/Chart.yaml +++ b/helm/portal/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.7 +version: 0.1.8 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/portal/README.md b/helm/portal/README.md index dbc2e503..a1287bff 100644 --- a/helm/portal/README.md +++ b/helm/portal/README.md @@ -1,6 +1,6 @@ # portal -![Version: 0.1.7](https://img.shields.io/badge/Version-0.1.7-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.8](https://img.shields.io/badge/Version-0.1.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 data-portal @@ -8,7 +8,7 @@ A Helm chart for gen3 data-portal | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/requestor/Chart.yaml b/helm/requestor/Chart.yaml index 2c4a8c43..552ae3bc 100644 --- a/helm/requestor/Chart.yaml +++ b/helm/requestor/Chart.yaml @@ -26,7 +26,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/requestor/README.md b/helm/requestor/README.md index 4b7c0cc2..706c6391 100644 --- a/helm/requestor/README.md +++ b/helm/requestor/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Requestor Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/revproxy/Chart.yaml b/helm/revproxy/Chart.yaml index ed6a92ba..8cc963aa 100644 --- a/helm/revproxy/Chart.yaml +++ b/helm/revproxy/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.10 +version: 0.1.11 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/revproxy/README.md b/helm/revproxy/README.md index 51ad7a6e..c038e4ea 100644 --- a/helm/revproxy/README.md +++ b/helm/revproxy/README.md @@ -1,6 +1,6 @@ # revproxy -![Version: 0.1.10](https://img.shields.io/badge/Version-0.1.10-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.11](https://img.shields.io/badge/Version-0.1.11-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 revproxy @@ -8,7 +8,7 @@ A Helm chart for gen3 revproxy | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/sheepdog/Chart.yaml b/helm/sheepdog/Chart.yaml index 7a68d313..5156d475 100644 --- a/helm/sheepdog/Chart.yaml +++ b/helm/sheepdog/Chart.yaml @@ -25,7 +25,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/sheepdog/README.md b/helm/sheepdog/README.md index 026324b0..405df79c 100644 --- a/helm/sheepdog/README.md +++ b/helm/sheepdog/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Sheepdog Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/sower/Chart.yaml b/helm/sower/Chart.yaml index c98d3d17..9dc8e8b7 100644 --- a/helm/sower/Chart.yaml +++ b/helm/sower/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/sower/README.md b/helm/sower/README.md index 9daf13f3..90bb3ae2 100644 --- a/helm/sower/README.md +++ b/helm/sower/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 sower | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/ssjdispatcher/Chart.yaml b/helm/ssjdispatcher/Chart.yaml index c5613110..4f97d26b 100644 --- a/helm/ssjdispatcher/Chart.yaml +++ b/helm/ssjdispatcher/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.6 +version: 0.1.7 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common diff --git a/helm/ssjdispatcher/README.md b/helm/ssjdispatcher/README.md index 46e84cfb..e09ea9f2 100644 --- a/helm/ssjdispatcher/README.md +++ b/helm/ssjdispatcher/README.md @@ -1,6 +1,6 @@ # ssjdispatcher -![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.7](https://img.shields.io/badge/Version-0.1.7-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 ssjdispatcher @@ -8,7 +8,7 @@ A Helm chart for gen3 ssjdispatcher | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | ## Values diff --git a/helm/wts/Chart.yaml b/helm/wts/Chart.yaml index 31869111..c572f64a 100644 --- a/helm/wts/Chart.yaml +++ b/helm/wts/Chart.yaml @@ -25,7 +25,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.7 + version: 0.1.8 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/wts/README.md b/helm/wts/README.md index a52f93a7..266f4fb4 100644 --- a/helm/wts/README.md +++ b/helm/wts/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 workspace token service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.7 | +| file://../common | common | 0.1.8 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values From a65340dec3940b5f223b55f22f5109ec097065da Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 3 Aug 2023 16:01:51 -0600 Subject: [PATCH 03/60] updating the elasticsearch version for the gen3 umbrella chart --- .secrets.baseline | 4 ++-- helm/gen3/Chart.yaml | 2 +- helm/gen3/README.md | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 32f7c4a2..d28066e8 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2023-08-03T21:53:32Z", + "generated_at": "2023-08-03T22:01:45Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -356,7 +356,7 @@ "hashed_secret": "1740c48fa3141d4851b14f97e3bc0f46f7670672", "is_secret": false, "is_verified": false, - "line_number": 117, + "line_number": 118, "type": "Secret Keyword" } ], diff --git a/helm/gen3/Chart.yaml b/helm/gen3/Chart.yaml index 9c567bb5..2dfe4231 100644 --- a/helm/gen3/Chart.yaml +++ b/helm/gen3/Chart.yaml @@ -90,7 +90,7 @@ dependencies: - name: elasticsearch - version: "0.1.5" + version: "0.1.6" repository: "file://../elasticsearch" condition: global.dev - name: postgresql diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 0f574a9d..6e20c654 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -24,7 +24,7 @@ Helm chart to deploy Gen3 Data Commons | file://../audit | audit | 0.1.10 | | file://../aws-es-proxy | aws-es-proxy | 0.1.7 | | file://../common | common | 0.1.8 | -| file://../elasticsearch | elasticsearch | 0.1.5 | +| file://../elasticsearch | elasticsearch | 0.1.6 | | file://../fence | fence | 0.1.14 | | file://../guppy | guppy | 0.1.9 | | file://../hatchery | hatchery | 0.1.7 | @@ -37,6 +37,7 @@ Helm chart to deploy Gen3 Data Commons | file://../requestor | requestor | 0.1.9 | | file://../revproxy | revproxy | 0.1.11 | | file://../sheepdog | sheepdog | 0.1.11 | +| file://../sower | sower | 0.1.6 | | file://../ssjdispatcher | ssjdispatcher | 0.1.7 | | file://../wts | wts | 0.1.11 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | From 1239a368b324b9c773ab6cea8989adca5605d4d4 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 3 Aug 2023 16:06:22 -0600 Subject: [PATCH 04/60] bumping sower version --- helm/gen3/Chart.yaml | 2 +- helm/gen3/README.md | 2 +- helm/sower/Chart.yaml | 2 +- helm/sower/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/helm/gen3/Chart.yaml b/helm/gen3/Chart.yaml index 2dfe4231..b94f8053 100644 --- a/helm/gen3/Chart.yaml +++ b/helm/gen3/Chart.yaml @@ -80,7 +80,7 @@ dependencies: repository: "file://../ssjdispatcher" condition: ssjdispatcher.enabled - name: sower - version: "0.1.6" + version: "0.1.7" condition: sower.enabled repository: "file://../sower" - name: wts diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 6e20c654..bc862aca 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -37,7 +37,7 @@ Helm chart to deploy Gen3 Data Commons | file://../requestor | requestor | 0.1.9 | | file://../revproxy | revproxy | 0.1.11 | | file://../sheepdog | sheepdog | 0.1.11 | -| file://../sower | sower | 0.1.6 | +| file://../sower | sower | 0.1.7 | | file://../ssjdispatcher | ssjdispatcher | 0.1.7 | | file://../wts | wts | 0.1.11 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | diff --git a/helm/sower/Chart.yaml b/helm/sower/Chart.yaml index 9dc8e8b7..95b847ab 100644 --- a/helm/sower/Chart.yaml +++ b/helm/sower/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.6 +version: 0.1.7 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/sower/README.md b/helm/sower/README.md index 90bb3ae2..8ccb3ee7 100644 --- a/helm/sower/README.md +++ b/helm/sower/README.md @@ -1,6 +1,6 @@ # sower -![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.7](https://img.shields.io/badge/Version-0.1.7-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) A Helm chart for gen3 sower From e28fd34f7dfc1a14459dbc65ec4a4c2ab9c449ee Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 3 Aug 2023 16:09:19 -0600 Subject: [PATCH 05/60] bumping gen3 chart version --- helm/gen3/Chart.yaml | 2 +- helm/gen3/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/helm/gen3/Chart.yaml b/helm/gen3/Chart.yaml index b94f8053..50e03461 100644 --- a/helm/gen3/Chart.yaml +++ b/helm/gen3/Chart.yaml @@ -111,7 +111,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.19 +version: 0.1.20 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/gen3/README.md b/helm/gen3/README.md index bc862aca..77af0751 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -1,6 +1,6 @@ # gen3 -![Version: 0.1.19](https://img.shields.io/badge/Version-0.1.19-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) +![Version: 0.1.20](https://img.shields.io/badge/Version-0.1.20-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) Helm chart to deploy Gen3 Data Commons From c38dcb814b8883b9dd2b0d0634c797e1636b7f3d Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 3 Aug 2023 16:14:49 -0600 Subject: [PATCH 06/60] adding a new line to the end of the file --- .secrets.baseline | 4 ++-- helm/gen3/values.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index d28066e8..24d4cf64 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2023-08-03T22:01:45Z", + "generated_at": "2023-08-03T22:14:44Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -365,7 +365,7 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 212, + "line_number": 203, "type": "Secret Keyword" } ], diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index 9e9532cc..d62d77cd 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -375,4 +375,4 @@ secrets: # -- (str) AWS access key ID. Overrides global key. awsAccessKeyId: # -- (str) AWS secret access key ID. Overrides global key. - awsSecretAccessKey: \ No newline at end of file + awsSecretAccessKey: From 33f702e0297b0a5bafc06a742e4a63ccd23583c1 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Fri, 4 Aug 2023 08:33:16 -0600 Subject: [PATCH 07/60] updating the fence usersync job documentation to reflect the changes in the location of the aws access and secret access keys that are used to allow the job s3 access. --- docs/fence_usersync_job.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fence_usersync_job.md b/docs/fence_usersync_job.md index a05ed7d6..b1890132 100644 --- a/docs/fence_usersync_job.md +++ b/docs/fence_usersync_job.md @@ -15,7 +15,7 @@ User lists can be synced from three sources: # S3 user.yaml Setup {#s3-setup} Please see [this](https://github.com/uc-cdis/fence/blob/master/docs/user.yaml_guide.md) documentation that details user.yaml formatting. -You can pull this file from an S3 bucket that is set in the `.Values.usersync.userYamlS3Path` field. Then input the iam credentials for a user that has read access to the specified S3 bucket in the `.Values.usersync.secrets.awsAccessKeyId` and `.Values.usersync.secrets.awsSecretAccessKey` fields. +You can pull this file from an S3 bucket that is set in the `.Values.usersync.userYamlS3Path` field. Then input the iam credentials for a user that has read access to the specified S3 bucket in `.Values.global.aws.awsAccessKeyId`/`.Values.global.aws.awsSecretAccessKey` or `.Values.secrets.awsAccessKeyId`/`.Values.secrets.awsSecretAccessKey` fields. As previously mentioned, if the `.Values.usersync.userYamlS3Path` string is set to "none", the user.yaml file from Fence values.yaml will be used. From ca7f84c8e8adc951290fda6b3a176527cb6540fc Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Fri, 4 Aug 2023 13:37:18 -0600 Subject: [PATCH 08/60] addinng documentation for External Secrets and how to configure a Global Iam user --- docs/external_secrets.md | 143 +++++++++++++++++++++++++++++++++++ docs/fence_usersync_job.md | 7 +- docs/global_iam_helm_user.md | 55 ++++++++++++++ 3 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 docs/external_secrets.md create mode 100644 docs/global_iam_helm_user.md diff --git a/docs/external_secrets.md b/docs/external_secrets.md new file mode 100644 index 00000000..32b4c355 --- /dev/null +++ b/docs/external_secrets.md @@ -0,0 +1,143 @@ +# External Secrets Operator + + "External Secrets Operator" is a tool that was created by the Kubernetes community to manage external secrets in a Kubernetes cluster. It allows you to fetch and sync external secret values from various external secret management systems into Kubernetes secrets. One of the external secret management systems it can connect to is AWS Secrets Manager. Secrets Manager allows for the secure storing of your secrets as well as the ability to periodically and automatically rotate your secrets. + +This document will guide you through setting up the essential resources to access your secrets in AWS Secrets Manager and download the External Secrets Operator Helm chart. This way, you can effectively utilize your stored secrets with Helm. + +## Download External Secrets Operator and Create Resources in AWS. +You can use the following Bash script to apply the External Secrets Operator to your cluster and create the necessary AWS resources. Fill in the variables below to get started: + +***Notice: +The Gen3 Helm chart has various jobs and uses for an Iam user. To enhance code reusability, we've implemented the option for jobs and services to share the same AWS IAM global user. If you would like to use the same Iam user for External Secrets and jobs like ["Fence Usersync"](fence_usersync_job.md) or our "AWS ES Proxy Service", you can follow [THIS](global_iam_helm_user.md) guide that details how to setup a Helm global user. In case you opt for a global IAM user, please comment out the "create_iam_policy" and "create_iam_user" functions at the end of the script.*** + +``` +#!/bin/bash + +AWS_ACCOUNT="" +region="" +iam_policy="" +iam_user="" + +helm_install() +{ + echo "# ------------------ Install external-secrets via helm --------------------------#" + helm repo add external-secrets https://charts.external-secrets.io + helm install external-secrets \ + external-secrets/external-secrets \ + -n external-secrets \ + --create-namespace \ + --set installCRDs=true +} + +create_iam_policy() +{ + echo "# ------------------ create iam policy for secrets manager --------------------------#" + POLICY_ARN=$(aws iam create-policy --policy-name $iam_policy --policy-document '{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "secretsmanager:ListSecrets", + "secretsmanager:GetSecretValue" + ], + "Resource": [ + "*" + ] + } + ] + }') + + iam_policy_arn=$(aws iam list-policies --query "Policies[?PolicyName=='$iam_policy'].Arn" --output text) + echo "Policy Arn: $iam_policy_arn" + # return $iam_policy_arn +} + +create_iam_user() +{ + echo "# ------------------ create user $iam_user --------------------------#" + aws iam create-user --user-name $iam_user + + echo "# ------------------ add iam user $iam_user to policy $iam_policy --------------------------#" + aws iam attach-user-policy --user-name $iam_user --policy-arn $iam_policy_arn + echo "aws iam attach-user-policy --user-name $iam_user --policy-arn $iam_policy_arn" + + echo "# ------------------ create access key and secret key for external-secrets --------------------------#" + aws iam create-access-key --user-name $iam_user > keys.json + access_key=$(jq -r .AccessKey.AccessKeyId keys.json) + secret_key=$(jq -r .AccessKey.SecretAccessKey keys.json) + kubectl create secret generic "$iam_user"-secret --from-literal=access-key=$access_key --from-literal=secret-access-key=$secret_key + rm keys.json +} + +helm_install +#comment out the below if using global iam user. +create_iam_policy +create_iam_user +``` + +***Please note that Terraform for the creation and population of Gen3 Secrets in Secrets Manager is in development currently. This Terraform will also create the Iam user and policies necessary to access these secrets.*** + +## Enabling External Secrets in Helm charts +To enable External Secrets to be used in a helm chart, you can set the `.Values.global.externalSecrets.deploy` field to "true" for an individual chart or globally by enabling this value in the Gen3 umbrella Helm chart. + +If you would like to only use External Secrets for specific charts, please ensure you set `.Values.global.externalSecrets.separate` to "true" in the appropriate charts to ensure a Secret Store can be created to authenticate with Secrets Manager. + +## Helm Iam User +If you are using a separate Iam user for Secrets Manager please follow the below instructions: + +This script Bash script at the beginning of this document should have created a secret titled "NameofIAMuser-user-secret" in your cluster. You will need to retrieve these values to input into your Helm chart for the Cluster Secret Store to authenticate with Secrets Manager. + + +Access Key: +``` +kubectl get secret "your secret name" -o jsonpath="{.data.access-key}" | base64 --decode +``` + + +Secret Access Key +``` +kubectl get secret "your secret name" -o jsonpath="{.data.secret-access-key}" | base64 --decode +``` + +You can paste the Iam access key and secret access key in the `.Values.secrets.awsAccessKeyId`/`.Values.secrets.awsSecretAccessKey` fields in the values.yaml file for the chart(s) you would like to use external secrets for. + +Please note that only some Helm charts are compatible with External Secrets currently. We hope to expand this functionality in the future. If a chart is able to use External Secrets, you can see a `.Values.externalSecrets` section in the values.yaml file. + +## How External Secrets Works. +External Secrets relies on three main resources to function properly. (The below have links to examples of each resource) +1. Aws-config- Contains Access and Secret Access keys used by the Cluster Secret Store to authenticate with AWS Secrets Manager +2. Cluster Secret Store- Resource to Authenticate with AWS Secrets Manager +3. External Secret- References the Secret Store and is used as a "map" to tell External Secrets Operator what secret to grab from External Secrets and the name of the Kubernetes Secret to create locally. + + Anatomy of an ExternalSecret: + ``` + apiVersion: external-secrets.io/v1beta1 + kind: ExternalSecret + metadata: + # Name of the External Secret resource + name: audit-g3auto + spec: + #How often to Sync with Secrets Manager + refreshInterval: 5m + secretStoreRef: + # The name of the Cluster Secret Store to use. + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + # What Kubernetes secret to create from the secret pulled from Secrets Manager. + name: audit-g3auto + creationPolicy: Owner + dataFrom: + - extract: + # The name of the secret pull from Secrets Manager + key: {{include "audit-g3auto" .}} + ``` + +The External Secrets resource will usually fail with "SecretSyncedError" when it cannot find the secret name that is supplied in Secrets Manager. If this happens, the secret may still exist in Kubernetes, but it will not be overwritten by the secret value in Secrets Manager. This is helpful to know if you want to enabled the use of Secrets Manager for some, but not all the secrets in a specific Helm chart. + +## Customizing the AWS Secrets Manager Secrets Name. +When pulling a secret from secrets manager, you want to ensure that the External Secret resource is referencing the proper name of the secret in Secrets Manager. +You can customize the name of the secret to pull from in the `.Values.externalSecrets` section of a Chart. You can see the name for the confiugrable secrets in a chart by looking in this section as well. + +Any string you put in this section will override the name of the secret that is pulled from Secrets Manager NOT the name of the Kubernetes secret that is created from the External Secret resource. diff --git a/docs/fence_usersync_job.md b/docs/fence_usersync_job.md index b1890132..a4230a0a 100644 --- a/docs/fence_usersync_job.md +++ b/docs/fence_usersync_job.md @@ -15,7 +15,10 @@ User lists can be synced from three sources: # S3 user.yaml Setup {#s3-setup} Please see [this](https://github.com/uc-cdis/fence/blob/master/docs/user.yaml_guide.md) documentation that details user.yaml formatting. -You can pull this file from an S3 bucket that is set in the `.Values.usersync.userYamlS3Path` field. Then input the iam credentials for a user that has read access to the specified S3 bucket in `.Values.global.aws.awsAccessKeyId`/`.Values.global.aws.awsSecretAccessKey` or `.Values.secrets.awsAccessKeyId`/`.Values.secrets.awsSecretAccessKey` fields. +You can pull this file from an S3 bucket that is set in the `.Values.usersync.userYamlS3Path` field. Then input the iam credentials for a user that has read access to the specified S3 bucket in the `.Values.secrets.awsAccessKeyId` and `.Values.secrets.awsSecretAccessKey` fields. + +***Notice: +The Gen3 Helm chart has various jobs and uses for an Iam user. To enhance code reusability, we've implemented the option for jobs and services to share the same AWS IAM global user. If you would like to use the same Iam user for Fence Usersync, External Secrets, etc.- you can follow [THIS](global_iam_helm_user.md) guide that details how to setup a Helm global user.*** As previously mentioned, if the `.Values.usersync.userYamlS3Path` string is set to "none", the user.yaml file from Fence values.yaml will be used. @@ -59,7 +62,7 @@ For an example of a dbGap auth file (csv), please see [this](https://github.com/ -# Other Customizations +## Other Customizations The `.Values.usersync.schedule` option can be set to customize the cron schedule expression. The default setting is to have the job run once every 30 minutes. The `.Values.usersync.custom_image` can be set to override the default "awshelper" image for the init container of the userync cronjob. \ No newline at end of file diff --git a/docs/global_iam_helm_user.md b/docs/global_iam_helm_user.md new file mode 100644 index 00000000..e8f68507 --- /dev/null +++ b/docs/global_iam_helm_user.md @@ -0,0 +1,55 @@ +# AWS Iam Global User + +For Helm code resusability, we have added the functionality to use one iam user for various jobs/services. + +We are currently in the process of integrating this user into our Terraform code. In the meantime, you can manually create a global user by referring to this guide. + +## What this user can do in Helm +- Fence Usersync Job +- ES Index Restore +- Restore PGdump +- External Secrets +- AWS ES Proxy Service + + + +Example policy containing all the proper permissions: +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "s3:GetObject", + "Resource": [ + "arn:aws:s3:::$BUCKET/$ENVIRONMENT/*", + # Fence Usersync Job: Name of the userYamlS3Path containing the user.yaml file + "arn:aws:s3:::$BUCKET/$ENVIRONMENT/$VERSION/elasticsearch/*", + # ES Index Restore Job: Name of the dbRestoreBucket with the proper path to the ES dump files. + "arn:aws:s3:::$BUCKET/$ENVIRONMENT/$VERSION/pgdumps/*" + # DB PG Dump Restore Job: Name of the dbRestoreBucket with the proper path to the SQL dump files. + ] + }, + { + "Effect": "Allow", + "Action": [ + "secretsmanager:ListSecrets", + "secretsmanager:GetSecretValue" + ], + "Resource": [ + "*" + # External Secrets: Leave as is to allow External Secrets access to your secrets in Secrets Manager. + ] + }, + { + "Effect": "Allow", + "Action": "es:*", + "Resource": "arn:aws:es:REGION:ACCOUNT_ID:domain/CLUSTER_NAME/*" + # AWS ES Proxy Service: Arn of your Elasticsearch Cluster in AWS. + } + ] +} +``` + +## After Creating the User +In order to integrate the user in Helm, paste in the values of your Access and Secret Access key in `.Values.global.aws.awsAccessKeyId` and `.Values.global.aws.awsSecretAccessKey` \ No newline at end of file From 8e7eec02f957f2a03968a58695b766769c2a8a5b Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Fri, 4 Aug 2023 13:41:40 -0600 Subject: [PATCH 09/60] fixing one of the external secret yaml files and changing the default settings for indexd --- helm/fence/templates/external-secret.yaml | 2 +- helm/indexd/README.md | 8 ++++---- helm/indexd/values.yaml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/helm/fence/templates/external-secret.yaml b/helm/fence/templates/external-secret.yaml index f37d8287..dd4e3f7f 100644 --- a/helm/fence/templates/external-secret.yaml +++ b/helm/fence/templates/external-secret.yaml @@ -82,5 +82,5 @@ spec: dataFrom: - extract: #name of secret in secrets manager - key: {{include "fenceSmDbcreds" .}} + key: {{include "fence-sm-dbcreds" .}} {{- end }} \ No newline at end of file diff --git a/helm/indexd/README.md b/helm/indexd/README.md index e8108d81..3c037814 100644 --- a/helm/indexd/README.md +++ b/helm/indexd/README.md @@ -30,7 +30,7 @@ A Helm chart for gen3 indexd | externalSecrets | map | `{"indexdSmDbcreds":null}` | External Secrets settings. | | externalSecrets.indexdSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":true,"separate":true},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -40,9 +40,9 @@ A Helm chart for gen3 indexd | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":true,"separate":true}` | External Secrets settings. | -| global.externalSecrets.deploy | bool | `true` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any indexd secrets you have deployed. | -| global.externalSecrets.separate | string | `true` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any indexd secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/indexd/values.yaml b/helm/indexd/values.yaml index 4f4e0ef5..c2302ec0 100644 --- a/helm/indexd/values.yaml +++ b/helm/indexd/values.yaml @@ -61,9 +61,9 @@ global: # -- (map) External Secrets settings. externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any indexd secrets you have deployed. - deploy: true + deploy: false # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: true + separate: false # -- (map) External Secrets settings. externalSecrets: From 7da2bc1e866a799eeff1555ec832e50f595c49bf Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 21 Aug 2023 15:03:21 -0600 Subject: [PATCH 10/60] updating the volume mount for settings.py --- helm/peregrine/README.md | 2 +- helm/peregrine/templates/deployment.yaml | 6 ++---- helm/peregrine/values.yaml | 4 ++++ helm/sheepdog/README.md | 2 +- helm/sheepdog/values.yaml | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/helm/peregrine/README.md b/helm/peregrine/README.md index 55b8da06..6f9f8c7b 100644 --- a/helm/peregrine/README.md +++ b/helm/peregrine/README.md @@ -100,7 +100,7 @@ A Helm chart for gen3 Peregrine service | serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | | serviceAccount.name | string | `""` | The name of the service account | | tolerations | list | `[]` | Tolerations for the pods | -| volumeMounts | list | `nil` | Volumes to mount to the container. | +| volumeMounts | list | `[{"mountPath":"/var/www/peregrine/settings.py","name":"config-volume","readOnly":true,"subPath":"settings.py"}]` | Volumes to mount to the container. | | volumes | list | `[{"emptyDir":{},"name":"shared-data"},{"name":"config-volume","secret":{"secretName":"peregrine-secret"}}]` | Volumes to attach to the container. | ---------------------------------------------- diff --git a/helm/peregrine/templates/deployment.yaml b/helm/peregrine/templates/deployment.yaml index 561df45c..ed223cda 100644 --- a/helm/peregrine/templates/deployment.yaml +++ b/helm/peregrine/templates/deployment.yaml @@ -147,11 +147,9 @@ spec: value: "False" - name: CONF_HOSTNAME value: {{ .Values.global.hostname }} + {{- with .Values.volumeMounts }} volumeMounts: - - name: "config-volume" - readOnly: true - mountPath: "/var/www/peregrine/wsgi.py" - subPath: "settings.py" + {{- toYaml . | nindent 10 }} ports: - name: http containerPort: 80 diff --git a/helm/peregrine/values.yaml b/helm/peregrine/values.yaml index fe92f044..bca29606 100644 --- a/helm/peregrine/values.yaml +++ b/helm/peregrine/values.yaml @@ -203,6 +203,10 @@ volumes: # -- (list) Volumes to mount to the container. volumeMounts: + - name: "config-volume" + readOnly: true + mountPath: "/var/www/peregrine/settings.py" + subPath: "settings.py" # Values to determine the labels that are used for the deployment, pod, etc. # -- (string) Valid options are "production" or "dev". If invalid option is set- the value will default to "dev". diff --git a/helm/sheepdog/README.md b/helm/sheepdog/README.md index 405df79c..7f707caf 100644 --- a/helm/sheepdog/README.md +++ b/helm/sheepdog/README.md @@ -122,7 +122,7 @@ A Helm chart for gen3 Sheepdog Service | strategy.rollingUpdate.maxSurge | int | `1` | Number of additional replicas to add during rollout. | | strategy.rollingUpdate.maxUnavailable | int | `0` | Maximum amount of pods that can be unavailable during the update. | | terminationGracePeriodSeconds | int | `50` | sheepdog transactions take forever - try to let the complete before termination | -| volumeMounts | list | `[{"mountPath":"/var/www/sheepdog/wsgi.py","name":"config-volume","readOnly":true,"subPath":"wsgi.py"}]` | Volumes to mount to the container. | +| volumeMounts | list | `[{"mountPath":"/var/www/sheepdog/settings.py","name":"config-volume","readOnly":true,"subPath":"settings.py"}]` | Volumes to mount to the container. | ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/sheepdog/values.yaml b/helm/sheepdog/values.yaml index 8a94905e..1ac1db3b 100644 --- a/helm/sheepdog/values.yaml +++ b/helm/sheepdog/values.yaml @@ -182,8 +182,8 @@ authNamespace: default volumeMounts: - name: "config-volume" readOnly: true - mountPath: "/var/www/sheepdog/wsgi.py" - subPath: "wsgi.py" + mountPath: "/var/www/sheepdog/settings.py" + subPath: "settings.py" # -- (map) Resource requests and limits for the containers in the pod resources: From f0fd53a6dfd785d3b8399e043d91286ba5e9b33b Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 21 Aug 2023 15:08:19 -0600 Subject: [PATCH 11/60] adding in the "end" function to values.yaml --- helm/peregrine/templates/deployment.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/helm/peregrine/templates/deployment.yaml b/helm/peregrine/templates/deployment.yaml index ed223cda..e554be55 100644 --- a/helm/peregrine/templates/deployment.yaml +++ b/helm/peregrine/templates/deployment.yaml @@ -150,6 +150,7 @@ spec: {{- with .Values.volumeMounts }} volumeMounts: {{- toYaml . | nindent 10 }} + {{- end }} ports: - name: http containerPort: 80 From 703b3416e5679bf227d8534f8e465942021c9808 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Wed, 23 Aug 2023 13:20:02 -0600 Subject: [PATCH 12/60] changing the gen3 umbrella chart to be able to use a local secret for external secrets --- .secrets.baseline | 4 ++-- helm/gen3/README.md | 3 +++ helm/gen3/templates/aws-config.yaml | 2 +- helm/gen3/templates/cluster-secret-store.yaml | 22 ++++++++++++++++++- helm/gen3/values.yaml | 5 +++++ 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 24d4cf64..3718a0a5 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2023-08-03T22:14:44Z", + "generated_at": "2023-08-23T19:17:36Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -365,7 +365,7 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 203, + "line_number": 208, "type": "Secret Keyword" } ], diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 77af0751..6dff3a79 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -201,6 +201,9 @@ Helm chart to deploy Gen3 Data Commons | ssjdispatcher.image | map | `{"repository":null,"tag":null}` | Docker image information. | | ssjdispatcher.image.repository | string | `nil` | The Docker image repository for the ssjdispatcher service. | | ssjdispatcher.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | +| useLocalSecret.enabled | bool | `false` | | +| useLocalSecret.localSecretName | string | `nil` | | +| useLocalSecret.localSecretNamespace | string | `nil` | | | wts.enabled | bool | `true` | Whether to deploy the wts subchart. | | wts.image | map | `{"repository":null,"tag":null}` | Docker image information. | | wts.image.repository | string | `nil` | The Docker image repository for the wts service. | diff --git a/helm/gen3/templates/aws-config.yaml b/helm/gen3/templates/aws-config.yaml index 5fff9698..0adbb034 100644 --- a/helm/gen3/templates/aws-config.yaml +++ b/helm/gen3/templates/aws-config.yaml @@ -1,3 +1,3 @@ -{{- if .Values.global.aws.awsSecretAccessKey}} +{{- if and .Values.global.aws.awsSecretAccessKey (not .Values.useLocalSecret.enabled) }} {{ include "common.awsconfig" . }} {{- end -}} \ No newline at end of file diff --git a/helm/gen3/templates/cluster-secret-store.yaml b/helm/gen3/templates/cluster-secret-store.yaml index 15558a80..1e01af1b 100644 --- a/helm/gen3/templates/cluster-secret-store.yaml +++ b/helm/gen3/templates/cluster-secret-store.yaml @@ -1,3 +1,23 @@ -{{ if .Values.global.externalSecrets.deploy }} +{{- if and .Values.global.externalSecrets.deploy (not .Values.useLocalSecret.enabled) }} {{ include "common.secretstore" . }} +{{- else if .Values.useLocalSecret.enabled }} +apiVersion: external-secrets.io/v1beta1 +kind: ClusterSecretStore +metadata: + name: {{.Chart.Name}}-secret-store +spec: + provider: + aws: + service: SecretsManager + region: us-east-1 + auth: + secretRef: + accessKeyIDSecretRef: + name: {{ .Values.useLocalSecret.localSecretName }} + key: access-key + namespace: {{ .Values.useLocalSecret.localSecretNamespace }} + secretAccessKeySecretRef: + name: {{ .Values.useLocalSecret.localSecretName }} + key: secret-access-key + namespace: {{ .Values.useLocalSecret.localSecretNamespace }} {{- end }} \ No newline at end of file diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index d62d77cd..92aad101 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -54,6 +54,11 @@ global: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override secrets you have deployed. deploy: false +useLocalSecret: + enabled: false + localSecretName: + localSecretNamespace: + # localSecretKey: # Dependancy Charts From f88cb7281dc4157bf82f5211f3768155b60c1da8 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Wed, 23 Aug 2023 14:42:30 -0600 Subject: [PATCH 13/60] fixing the include logic for sheepdog aws-config --- helm/sheepdog/templates/aws-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/sheepdog/templates/aws-config.yaml b/helm/sheepdog/templates/aws-config.yaml index 745635c1..398770d3 100644 --- a/helm/sheepdog/templates/aws-config.yaml +++ b/helm/sheepdog/templates/aws-config.yaml @@ -1,3 +1,3 @@ -{{- if or (.Values.dbRestore) (.Values.global.externalSecrets.deploy) }} +{{- if or (.Values.secrets.awsSecretAccessKey) (.Values.global.aws.awsSecretAccessKey ) }} {{ include "common.awsconfig" . }} {{- end -}} \ No newline at end of file From 4131806285098d860af2953f273b0d663f713b93 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 28 Aug 2023 14:33:39 -0600 Subject: [PATCH 14/60] Editing the external secrets yaml files so unstructured secrets are pulled properly from secrets manager. Also, moving the local secret configuration option to the global section. --- .secrets.baseline | 4 +-- helm/arborist/templates/external-secret.yaml | 5 ++-- helm/audit/templates/external-secret.yaml | 10 +++++--- helm/common/templates/_restore_pgdump.tpl | 5 ++++ helm/fence/templates/external-secret.yaml | 25 +++++++++++-------- helm/gen3/README.md | 5 +--- helm/gen3/templates/aws-config.yaml | 2 +- helm/gen3/templates/cluster-secret-store.yaml | 12 ++++----- helm/gen3/values.yaml | 10 +++----- helm/indexd/templates/external-secrets.yaml | 5 ++-- .../templates/external-secret.yaml | 5 ++-- helm/metadata/templates/external-secret.yaml | 5 ++-- helm/peregrine/templates/external-secret.yaml | 5 ++-- helm/requestor/templates/external-secret.yaml | 7 +++--- helm/sheepdog/templates/external-secrets.yaml | 5 ++-- helm/wts/templates/external-secret.yaml | 5 ++-- 16 files changed, 65 insertions(+), 50 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 3718a0a5..1877bf36 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2023-08-23T19:17:36Z", + "generated_at": "2023-08-28T20:28:15Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -365,7 +365,7 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 208, + "line_number": 206, "type": "Secret Keyword" } ], diff --git a/helm/arborist/templates/external-secret.yaml b/helm/arborist/templates/external-secret.yaml index b0bca685..42ca56e0 100644 --- a/helm/arborist/templates/external-secret.yaml +++ b/helm/arborist/templates/external-secret.yaml @@ -11,8 +11,9 @@ spec: target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: data + remoteRef: #name of secret in secrets manager key: {{include "arborist-sm-dbcreds" .}} {{- end }} \ No newline at end of file diff --git a/helm/audit/templates/external-secret.yaml b/helm/audit/templates/external-secret.yaml index 56c36756..fca176ac 100644 --- a/helm/audit/templates/external-secret.yaml +++ b/helm/audit/templates/external-secret.yaml @@ -11,8 +11,9 @@ spec: target: name: audit-g3auto creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: audit-service-config.yaml + remoteRef: #name of secret in secrets manager key: {{include "audit-g3auto" .}} --- @@ -28,8 +29,9 @@ spec: target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: data + remoteRef: #name of secret in secrets manager key: {{include "audit-sm-dbcreds" .}} {{- end }} \ No newline at end of file diff --git a/helm/common/templates/_restore_pgdump.tpl b/helm/common/templates/_restore_pgdump.tpl index 3f7b4967..dffa024d 100644 --- a/helm/common/templates/_restore_pgdump.tpl +++ b/helm/common/templates/_restore_pgdump.tpl @@ -18,6 +18,11 @@ spec: - name: cred-volume secret: secretName: {{.Chart.Name}}-aws-config + {{- if .Values.global.aws.useLocalSecret.enabled -}} + secretName: {{ .Values.global.aws.useLocalSecret.localSecretName }} + {{ else }} + secretName: {{.Chart.Name}}-aws-config + {{ end }} containers: - name: restore-dbs image: quay.io/cdis/awshelper:master diff --git a/helm/fence/templates/external-secret.yaml b/helm/fence/templates/external-secret.yaml index dd4e3f7f..ece35301 100644 --- a/helm/fence/templates/external-secret.yaml +++ b/helm/fence/templates/external-secret.yaml @@ -11,8 +11,9 @@ spec: target: name: fence-jwt-keys creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: jwt_private_key.pem + remoteRef: #name of secret in secrets manager key: {{include "fence-jwt-keys" .}} --- @@ -28,8 +29,9 @@ spec: target: name: fence-google-app-creds-secret creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: fence_google_app_creds_secret.json + remoteRef: #name of secret in secrets manager key: {{include "fence-google-app-creds-secret" .}} --- @@ -45,8 +47,9 @@ spec: target: name: fence-google-storage-creds-secret creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: fence_google_storage_creds_secret.json + remoteRef: #name of secret in secrets manager key: {{include "fence-google-storage-creds-secret" .}} --- @@ -62,8 +65,9 @@ spec: target: name: fence-config creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: fence-config.yaml + remoteRef: #name of secret in secrets manager key: {{include "fence-config" .}} --- @@ -79,8 +83,9 @@ spec: target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: data + remoteRef: #name of secret in secrets manager key: {{include "fence-sm-dbcreds" .}} {{- end }} \ No newline at end of file diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 6dff3a79..d8d73408 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -85,7 +85,7 @@ Helm chart to deploy Gen3 Data Commons | gitops.json | string | `nil` | multiline string - gitops.json | | gitops.logo | string | `nil` | - logo in base64 | | gitops.sponsors | string | `nil` | | -| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | +| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false,"useLocalSecret":{"enabled":false,"localSecretName":null,"localSecretNamespace":null}}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | | global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | @@ -201,9 +201,6 @@ Helm chart to deploy Gen3 Data Commons | ssjdispatcher.image | map | `{"repository":null,"tag":null}` | Docker image information. | | ssjdispatcher.image.repository | string | `nil` | The Docker image repository for the ssjdispatcher service. | | ssjdispatcher.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | -| useLocalSecret.enabled | bool | `false` | | -| useLocalSecret.localSecretName | string | `nil` | | -| useLocalSecret.localSecretNamespace | string | `nil` | | | wts.enabled | bool | `true` | Whether to deploy the wts subchart. | | wts.image | map | `{"repository":null,"tag":null}` | Docker image information. | | wts.image.repository | string | `nil` | The Docker image repository for the wts service. | diff --git a/helm/gen3/templates/aws-config.yaml b/helm/gen3/templates/aws-config.yaml index 0adbb034..bec10059 100644 --- a/helm/gen3/templates/aws-config.yaml +++ b/helm/gen3/templates/aws-config.yaml @@ -1,3 +1,3 @@ -{{- if and .Values.global.aws.awsSecretAccessKey (not .Values.useLocalSecret.enabled) }} +{{- if and .Values.global.aws.awsSecretAccessKey (not .Values.global.aws.useLocalSecret.enabled) }} {{ include "common.awsconfig" . }} {{- end -}} \ No newline at end of file diff --git a/helm/gen3/templates/cluster-secret-store.yaml b/helm/gen3/templates/cluster-secret-store.yaml index 1e01af1b..6251d0fb 100644 --- a/helm/gen3/templates/cluster-secret-store.yaml +++ b/helm/gen3/templates/cluster-secret-store.yaml @@ -1,6 +1,6 @@ -{{- if and .Values.global.externalSecrets.deploy (not .Values.useLocalSecret.enabled) }} +{{- if and .Values.global.externalSecrets.deploy (not .Values.global.aws.useLocalSecret.enabled) }} {{ include "common.secretstore" . }} -{{- else if .Values.useLocalSecret.enabled }} +{{- else if .Values.global.aws.useLocalSecret.enabled }} apiVersion: external-secrets.io/v1beta1 kind: ClusterSecretStore metadata: @@ -13,11 +13,11 @@ spec: auth: secretRef: accessKeyIDSecretRef: - name: {{ .Values.useLocalSecret.localSecretName }} + name: {{ .Values.global.aws.useLocalSecret.localSecretName }} key: access-key - namespace: {{ .Values.useLocalSecret.localSecretNamespace }} + namespace: {{ .Values.global.aws.useLocalSecret.localSecretNamespace }} secretAccessKeySecretRef: - name: {{ .Values.useLocalSecret.localSecretName }} + name: {{ .Values.global.aws.useLocalSecret.localSecretName }} key: secret-access-key - namespace: {{ .Values.useLocalSecret.localSecretNamespace }} + namespace: {{ .Values.global.aws.useLocalSecret.localSecretNamespace }} {{- end }} \ No newline at end of file diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index 92aad101..dc2c930c 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -11,6 +11,10 @@ global: awsAccessKeyId: # -- (string) Credentials for AWS stuff. awsSecretAccessKey: + useLocalSecret: + enabled: false + localSecretName: + localSecretNamespace: # -- (bool) Deploys postgres/elasticsearch for dev dev: true postgres: @@ -54,12 +58,6 @@ global: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override secrets you have deployed. deploy: false -useLocalSecret: - enabled: false - localSecretName: - localSecretNamespace: - # localSecretKey: - # Dependancy Charts ambassador: diff --git a/helm/indexd/templates/external-secrets.yaml b/helm/indexd/templates/external-secrets.yaml index 5921b810..7a00916f 100644 --- a/helm/indexd/templates/external-secrets.yaml +++ b/helm/indexd/templates/external-secrets.yaml @@ -11,8 +11,9 @@ spec: target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: data + remoteRef: #name of secret in secrets manager key: {{include "indexd-sm-dbcreds" .}} {{- end }} \ No newline at end of file diff --git a/helm/manifestservice/templates/external-secret.yaml b/helm/manifestservice/templates/external-secret.yaml index 51d31656..27b2c143 100644 --- a/helm/manifestservice/templates/external-secret.yaml +++ b/helm/manifestservice/templates/external-secret.yaml @@ -11,8 +11,9 @@ spec: target: name: manifestservice-g3auto creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: config.json + remoteRef: #name of secret in secrets manager key: {{include "manifestservice-g3auto" .}} {{- end }} \ No newline at end of file diff --git a/helm/metadata/templates/external-secret.yaml b/helm/metadata/templates/external-secret.yaml index 179c5f77..478d262e 100644 --- a/helm/metadata/templates/external-secret.yaml +++ b/helm/metadata/templates/external-secret.yaml @@ -11,8 +11,9 @@ spec: target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: data + remoteRef: #name of secret in secrets manager key: {{include "metadata-sm-dbcreds" .}} {{- end }} \ No newline at end of file diff --git a/helm/peregrine/templates/external-secret.yaml b/helm/peregrine/templates/external-secret.yaml index a25b7a45..92cfab01 100644 --- a/helm/peregrine/templates/external-secret.yaml +++ b/helm/peregrine/templates/external-secret.yaml @@ -11,8 +11,9 @@ spec: target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: data + remoteRef: #name of secret in secrets manager key: {{include "peregrine-sm-dbcreds" .}} {{- end }} \ No newline at end of file diff --git a/helm/requestor/templates/external-secret.yaml b/helm/requestor/templates/external-secret.yaml index 9476e59b..01e37420 100644 --- a/helm/requestor/templates/external-secret.yaml +++ b/helm/requestor/templates/external-secret.yaml @@ -11,8 +11,9 @@ spec: target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: data + remoteRef: #name of secret in secrets manager - key: {{include "requestor-sm-dbcreds" .}} + key: {{nclude "requestor-sm-dbcreds" .}} {{- end }} \ No newline at end of file diff --git a/helm/sheepdog/templates/external-secrets.yaml b/helm/sheepdog/templates/external-secrets.yaml index afd441e2..25c8912f 100644 --- a/helm/sheepdog/templates/external-secrets.yaml +++ b/helm/sheepdog/templates/external-secrets.yaml @@ -11,8 +11,9 @@ spec: target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: data + remoteRef: #name of secret in secrets manager key: {{include "sheepdog-sm-dbcreds" .}} {{- end }} \ No newline at end of file diff --git a/helm/wts/templates/external-secret.yaml b/helm/wts/templates/external-secret.yaml index d18abd46..0ac706f6 100644 --- a/helm/wts/templates/external-secret.yaml +++ b/helm/wts/templates/external-secret.yaml @@ -11,8 +11,9 @@ spec: target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner - dataFrom: - - extract: + data: + - secretKey: data + remoteRef: #name of secret in secrets manager key: {{include "wts-sm-dbcreds" .}} {{- end }} \ No newline at end of file From e45b280bcae6f50c5242f21f7ca1e912cfd6af1d Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 28 Aug 2023 15:25:26 -0600 Subject: [PATCH 15/60] fixing small typo --- helm/requestor/templates/external-secret.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/requestor/templates/external-secret.yaml b/helm/requestor/templates/external-secret.yaml index 01e37420..048097fc 100644 --- a/helm/requestor/templates/external-secret.yaml +++ b/helm/requestor/templates/external-secret.yaml @@ -15,5 +15,5 @@ spec: - secretKey: data remoteRef: #name of secret in secrets manager - key: {{nclude "requestor-sm-dbcreds" .}} + key: {{include "requestor-sm-dbcreds" .}} {{- end }} \ No newline at end of file From bb6235cecd2fe35b5c0a4e92be02d31d4f7d467d Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Tue, 29 Aug 2023 15:04:22 -0600 Subject: [PATCH 16/60] modifying the documentation as I added the ability to use a local secret for external secrets and fence. Edited the fence cronjob so it can now use a local secret if supplied. --- .secrets.baseline | 6 +++--- docs/external_secrets.md | 10 +++++++--- docs/fence_usersync_job.md | 2 ++ helm/fence/README.md | 8 ++++++-- helm/fence/templates/usersync-cron.yaml | 4 ++++ helm/fence/values.yaml | 8 ++++++++ helm/gen3/README.md | 4 ++++ helm/gen3/values.yaml | 4 ++++ 8 files changed, 38 insertions(+), 8 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 1877bf36..72a90745 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2023-08-28T20:28:15Z", + "generated_at": "2023-08-29T21:02:31Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -347,7 +347,7 @@ "hashed_secret": "5d07e1b80e448a213b392049888111e1779a52db", "is_secret": false, "is_verified": false, - "line_number": 1944, + "line_number": 1952, "type": "Secret Keyword" } ], @@ -365,7 +365,7 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 206, + "line_number": 210, "type": "Secret Keyword" } ], diff --git a/docs/external_secrets.md b/docs/external_secrets.md index 32b4c355..0852135d 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -102,6 +102,8 @@ kubectl get secret "your secret name" -o jsonpath="{.data.secret-access-key}" | You can paste the Iam access key and secret access key in the `.Values.secrets.awsAccessKeyId`/`.Values.secrets.awsSecretAccessKey` fields in the values.yaml file for the chart(s) you would like to use external secrets for. +If you are deploying external secrets with the Gen3 umbrella chart, you can utilize a local secret to avoid pasting credentials in the values.yaml file. Just set `.global.aws.useLocalSecret.enabled` to true and supply your secret name. + Please note that only some Helm charts are compatible with External Secrets currently. We hope to expand this functionality in the future. If a chart is able to use External Secrets, you can see a `.Values.externalSecrets` section in the values.yaml file. ## How External Secrets Works. @@ -128,9 +130,11 @@ External Secrets relies on three main resources to function properly. (The below # What Kubernetes secret to create from the secret pulled from Secrets Manager. name: audit-g3auto creationPolicy: Owner - dataFrom: - - extract: - # The name of the secret pull from Secrets Manager + data: + # the key inside the new Kubernetes secret + - secretKey: audit-service-config.yaml + remoteRef: + #name of secret in secrets manager key: {{include "audit-g3auto" .}} ``` diff --git a/docs/fence_usersync_job.md b/docs/fence_usersync_job.md index a4230a0a..dc8d6ea8 100644 --- a/docs/fence_usersync_job.md +++ b/docs/fence_usersync_job.md @@ -17,6 +17,8 @@ Please see [this](https://github.com/uc-cdis/fence/blob/master/docs/user.yaml_gu You can pull this file from an S3 bucket that is set in the `.Values.usersync.userYamlS3Path` field. Then input the iam credentials for a user that has read access to the specified S3 bucket in the `.Values.secrets.awsAccessKeyId` and `.Values.secrets.awsSecretAccessKey` fields. +You can utilize a local secret to avoid pasting credentials in the values.yaml file. Just set `.global.aws.useLocalSecret.enabled` to true and supply your secret name. + ***Notice: The Gen3 Helm chart has various jobs and uses for an Iam user. To enhance code reusability, we've implemented the option for jobs and services to share the same AWS IAM global user. If you would like to use the same Iam user for Fence Usersync, External Secrets, etc.- you can follow [THIS](global_iam_helm_user.md) guide that details how to setup a Helm global user.*** diff --git a/helm/fence/README.md b/helm/fence/README.md index af3a93ac..09a300ce 100644 --- a/helm/fence/README.md +++ b/helm/fence/README.md @@ -96,11 +96,15 @@ A Helm chart for gen3 Fence | externalSecrets.fenceJwtKeys | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-jwt-keys" | | externalSecrets.fenceSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","syncFromDbgap":false,"tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | -| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | +| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false,"useLocalSecret":{"enabled":false,"localSecretName":null,"localSecretNamespace":null}},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","syncFromDbgap":false,"tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | +| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false,"useLocalSecret":{"enabled":false,"localSecretName":null,"localSecretNamespace":null}}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | | global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | +| global.aws.useLocalSecret | map | `{"enabled":false,"localSecretName":null,"localSecretNamespace":null}` | Local secret setting if using a pre-exising secret. | +| global.aws.useLocalSecret.enabled | bool | `false` | Set to true if you would like to use a secret that is already running on your cluster. | +| global.aws.useLocalSecret.localSecretName | string | `nil` | Name of the local secret. | +| global.aws.useLocalSecret.localSecretNamespace | string | `nil` | Namespace of the local secret. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | diff --git a/helm/fence/templates/usersync-cron.yaml b/helm/fence/templates/usersync-cron.yaml index 3d8d8316..7bf9d8b8 100644 --- a/helm/fence/templates/usersync-cron.yaml +++ b/helm/fence/templates/usersync-cron.yaml @@ -52,7 +52,11 @@ spec: emptyDir: {} - name: cred-volume secret: + {{- if .Values.global.aws.useLocalSecret.enabled }} + secretName: {{ .Values.global.aws.useLocalSecret.localSecretName }} + {{- else }} secretName: {{.Chart.Name}}-aws-config + {{- end }} initContainers: - name: wait-for-fence image: curlimages/curl:latest diff --git a/helm/fence/values.yaml b/helm/fence/values.yaml index 287d28b1..300fd24a 100644 --- a/helm/fence/values.yaml +++ b/helm/fence/values.yaml @@ -12,6 +12,14 @@ global: awsAccessKeyId: # -- (string) Credentials for AWS stuff. awsSecretAccessKey: + # -- (map) Local secret setting if using a pre-exising secret. + useLocalSecret: + # -- (bool) Set to true if you would like to use a secret that is already running on your cluster. + enabled: false + # -- (string) Name of the local secret. + localSecretName: + # -- (string) Namespace of the local secret. + localSecretNamespace: # -- (bool) Whether the deployment is for development purposes. dev: true # -- (map) Postgres database configuration. diff --git a/helm/gen3/README.md b/helm/gen3/README.md index d8d73408..c1cbb407 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -89,6 +89,10 @@ Helm chart to deploy Gen3 Data Commons | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | | global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | +| global.aws.useLocalSecret | map | `{"enabled":false,"localSecretName":null,"localSecretNamespace":null}` | Local secret setting if using a pre-exising secret. | +| global.aws.useLocalSecret.enabled | bool | `false` | Set to true if you would like to use a secret that is already running on your cluster. | +| global.aws.useLocalSecret.localSecretName | string | `nil` | Name of the local secret. | +| global.aws.useLocalSecret.localSecretNamespace | string | `nil` | Namespace of the local secret. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Deploys postgres/elasticsearch for dev | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index dc2c930c..7c0c0839 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -11,9 +11,13 @@ global: awsAccessKeyId: # -- (string) Credentials for AWS stuff. awsSecretAccessKey: + # -- (map) Local secret setting if using a pre-exising secret. useLocalSecret: + # -- (bool) Set to true if you would like to use a secret that is already running on your cluster. enabled: false + # -- (string) Name of the local secret. localSecretName: + # -- (string) Namespace of the local secret. localSecretNamespace: # -- (bool) Deploys postgres/elasticsearch for dev dev: true From 20b337959f38a379df936e172aa4751c78f703bd Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Thu, 7 Sep 2023 17:23:26 -0600 Subject: [PATCH 17/60] Simplify dbcreds externalSecrets --- .secrets.baseline | 332 ++++-------------- helm/ambassador/README.md | 1 - helm/ambassador/values.yaml | 3 +- helm/arborist/README.md | 9 +- helm/arborist/templates/_helpers.tpl | 21 -- helm/arborist/templates/db-init.yaml | 5 +- helm/arborist/templates/external-secret.yaml | 20 +- helm/arborist/values.yaml | 11 +- helm/argo-wrapper/README.md | 1 - helm/argo-wrapper/values.yaml | 3 +- helm/audit/README.md | 9 +- helm/audit/templates/_helpers.tpl | 10 - helm/audit/templates/db-init.yaml | 5 +- helm/audit/templates/external-secret.yaml | 20 +- helm/audit/values.yaml | 11 +- helm/aws-es-proxy/README.md | 1 - helm/aws-es-proxy/values.yaml | 3 +- helm/common/README.md | 5 +- helm/common/templates/_db_setup_job.tpl | 30 ++ helm/common/templates/_external_secrets.tpl | 36 ++ helm/common/values.yaml | 9 +- helm/dicom-server/README.md | 1 - helm/dicom-server/values.yaml | 3 +- helm/dicom-viewer/README.md | 1 - helm/dicom-viewer/values.yaml | 3 +- helm/elasticsearch/README.md | 1 - helm/elasticsearch/values.yaml | 3 +- helm/fence/README.md | 11 +- helm/fence/templates/db-init.yaml | 5 +- helm/fence/templates/external-secret.yaml | 20 +- helm/fence/values.yaml | 13 +- helm/gen3/README.md | 4 +- helm/gen3/values.yaml | 5 +- helm/guppy/README.md | 7 +- helm/guppy/values.yaml | 11 +- helm/hatchery/README.md | 5 +- helm/hatchery/values.yaml | 9 +- helm/indexd/README.md | 11 +- helm/indexd/templates/_helpers.tpl | 11 - helm/indexd/templates/db-init.yaml | 2 + helm/indexd/templates/external-secrets.yaml | 20 +- helm/indexd/values.yaml | 13 +- helm/manifestservice/README.md | 1 - helm/manifestservice/values.yaml | 3 +- helm/metadata/README.md | 9 +- helm/metadata/templates/_helpers.tpl | 22 -- helm/metadata/templates/external-secret.yaml | 20 +- helm/metadata/values.yaml | 11 +- helm/peregrine/README.md | 9 +- helm/peregrine/templates/db-init.yaml | 5 +- helm/peregrine/templates/external-secret.yaml | 20 +- helm/peregrine/values.yaml | 11 +- helm/pidgin/README.md | 5 +- helm/pidgin/values.yaml | 9 +- helm/portal/README.md | 7 +- helm/portal/values.yaml | 11 +- helm/requestor/README.md | 9 +- helm/requestor/templates/_helpers.tpl | 24 +- helm/requestor/templates/db-init.yaml | 5 +- helm/requestor/templates/external-secret.yaml | 20 +- helm/requestor/values.yaml | 11 +- helm/revproxy/README.md | 9 +- helm/revproxy/values.yaml | 11 +- helm/sheepdog/README.md | 9 +- helm/sheepdog/templates/_helpers.tpl | 24 +- helm/sheepdog/templates/external-secrets.yaml | 20 +- helm/sheepdog/values.yaml | 11 +- helm/sower/README.md | 5 +- helm/sower/values.yaml | 9 +- helm/ssjdispatcher/README.md | 5 +- helm/ssjdispatcher/values.yaml | 9 +- helm/wts/README.md | 9 +- helm/wts/templates/_helpers.tpl | 22 -- helm/wts/templates/db-init.yaml | 5 +- helm/wts/templates/external-secret.yaml | 20 +- helm/wts/values.yaml | 11 +- 76 files changed, 353 insertions(+), 742 deletions(-) create mode 100644 helm/common/templates/_external_secrets.tpl diff --git a/.secrets.baseline b/.secrets.baseline index 72a90745..e2a9d95b 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2023-08-29T21:02:31Z", + "generated_at": "2023-09-07T23:22:53Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -127,85 +127,43 @@ } ], "helm/arborist/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 34, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 54, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 56, + "line_number": 55, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 74, + "line_number": 73, "type": "Secret Keyword" } ], "helm/audit/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 43, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 63, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 65, + "line_number": 64, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 85, + "line_number": 84, "type": "Secret Keyword" } ], "helm/common/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 11, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 22, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 24, + "line_number": 23, "type": "Secret Keyword" } ], @@ -230,14 +188,14 @@ "hashed_secret": "b47233f6f28e9716c72d5eba0278edea3a24baad", "is_secret": false, "is_verified": false, - "line_number": 39, + "line_number": 38, "type": "Secret Keyword" }, { "hashed_secret": "3f6d5580af2ddf647ca25346aa6ec9c434577d05", "is_secret": false, "is_verified": false, - "line_number": 55, + "line_number": 54, "type": "Secret Keyword" } ], @@ -246,44 +204,44 @@ "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "is_secret": false, "is_verified": false, - "line_number": 79, + "line_number": 80, "type": "Secret Keyword" } ], "helm/fence/README.md": [ { - "hashed_secret": "49bed5bac5cc06bafd528df89918bf34973861ec", + "hashed_secret": "4d10c0e4e0b7e73c9e709a15b81dbfa7ed3d91cc", "is_secret": false, "is_verified": false, - "line_number": 93, + "line_number": 92, "type": "Secret Keyword" }, { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", + "hashed_secret": "b266a6d0f00bb36f6b98134bf4cec71f2d7943a3", "is_secret": false, "is_verified": false, - "line_number": 106, + "line_number": 99, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 108, + "line_number": 124, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 135, + "line_number": 151, "type": "Secret Keyword" }, { "hashed_secret": "9d8fada0e01336e865c461bb3549084d206fe6da", "is_secret": false, "is_verified": false, - "line_number": 181, + "line_number": 197, "type": "Secret Keyword" } ], @@ -347,16 +305,23 @@ "hashed_secret": "5d07e1b80e448a213b392049888111e1779a52db", "is_secret": false, "is_verified": false, - "line_number": 1952, + "line_number": 1955, "type": "Secret Keyword" } ], "helm/gen3/README.md": [ + { + "hashed_secret": "b266a6d0f00bb36f6b98134bf4cec71f2d7943a3", + "is_secret": false, + "is_verified": false, + "line_number": 88, + "type": "Secret Keyword" + }, { "hashed_secret": "1740c48fa3141d4851b14f97e3bc0f46f7670672", "is_secret": false, "is_verified": false, - "line_number": 118, + "line_number": 122, "type": "Secret Keyword" } ], @@ -365,60 +330,32 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 210, + "line_number": 211, "type": "Secret Keyword" } ], "helm/guppy/README.md": [ - { - "hashed_secret": "0d5cd5f3caaaf8354a6c62816b97bcae006d4bcf", - "is_secret": false, - "is_verified": false, - "line_number": 43, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 60, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 62, + "line_number": 61, "type": "Secret Keyword" } ], "helm/hatchery/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 30, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 47, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 49, + "line_number": 48, "type": "Secret Keyword" }, { "hashed_secret": "e94cc2a86b04ad4ddc98fcbf91ed236437939d47", "is_secret": false, "is_verified": false, - "line_number": 57, + "line_number": 56, "type": "Secret Keyword" } ], @@ -427,44 +364,30 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 186, + "line_number": 189, "type": "Secret Keyword" } ], "helm/indexd/README.md": [ - { - "hashed_secret": "0d5cd5f3caaaf8354a6c62816b97bcae006d4bcf", - "is_secret": false, - "is_verified": false, - "line_number": 33, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 53, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 55, + "line_number": 54, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 74, + "line_number": 73, "type": "Secret Keyword" }, { "hashed_secret": "1cc98556e7b1353c7bd08344f9190808b0d3d6d4", "is_secret": true, "is_verified": false, - "line_number": 108, + "line_number": 107, "type": "Secret Keyword" } ], @@ -482,11 +405,11 @@ "hashed_secret": "611f2e9064b518afdb23f201321f39029dd28917", "is_secret": false, "is_verified": false, - "line_number": 86, + "line_number": 85, "type": "Secret Keyword" } ], - "helm/manifestservice/templates/metadataservice-creds.yaml": [ + "helm/manifestservice/templates/manifestservice-creds.yaml": [ { "hashed_secret": "d2e2ab0f407e4ee3cf2ab87d61c31b25a74085e5", "is_secret": false, @@ -496,69 +419,41 @@ } ], "helm/metadata/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 43, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 63, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 65, + "line_number": 64, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 84, + "line_number": 83, "type": "Secret Keyword" } ], "helm/peregrine/README.md": [ - { - "hashed_secret": "4e7b6794afbe3027589b92744144f18a3920b115", - "is_secret": false, - "is_verified": false, - "line_number": 34, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 54, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 56, + "line_number": 55, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 72, + "line_number": 71, "type": "Secret Keyword" }, { "hashed_secret": "7d4e263f1ae83868444f5327219830493a7d1486", "is_secret": false, "is_verified": false, - "line_number": 104, + "line_number": 103, "type": "Secret Keyword" } ], @@ -581,32 +476,18 @@ } ], "helm/pidgin/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 36, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 53, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 55, + "line_number": 54, "type": "Secret Keyword" }, { "hashed_secret": "abb751db44bcfd1bb9d4ad53e40138422abd739e", "is_secret": false, "is_verified": false, - "line_number": 67, + "line_number": 66, "type": "Secret Keyword" } ], @@ -625,25 +506,11 @@ "line_number": 41, "type": "Base64 High Entropy String" }, - { - "hashed_secret": "0d5cd5f3caaaf8354a6c62816b97bcae006d4bcf", - "is_secret": false, - "is_verified": false, - "line_number": 42, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 59, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 61, + "line_number": 60, "type": "Secret Keyword" } ], @@ -651,66 +518,45 @@ { "hashed_secret": "08eeb737b239bdb7362a875b90e22c10b8826b20", "is_verified": false, - "line_number": 469, + "line_number": 472, "type": "Base64 High Entropy String" }, { "hashed_secret": "eb9739c6625f06b4ab73035223366dda6262ae77", "is_verified": false, - "line_number": 472, + "line_number": 475, "type": "Base64 High Entropy String" } ], "helm/requestor/README.md": [ - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 63, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 65, + "line_number": 64, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 88, + "line_number": 87, "type": "Secret Keyword" } ], "helm/revproxy/README.md": [ - { - "hashed_secret": "5f0d5766b5954edbce68e73920428d26b9a293c8", - "is_secret": false, - "is_verified": false, - "line_number": 29, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 46, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 48, + "line_number": 47, "type": "Secret Keyword" }, { "hashed_secret": "abb751db44bcfd1bb9d4ad53e40138422abd739e", "is_secret": false, "is_verified": false, - "line_number": 73, + "line_number": 74, "type": "Secret Keyword" } ], @@ -724,53 +570,39 @@ } ], "helm/sheepdog/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 43, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 63, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 65, + "line_number": 64, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 80, + "line_number": 79, "type": "Secret Keyword" }, { "hashed_secret": "c2c4e52c03a03ce3efeb21eb202d301018d4548e", "is_secret": false, "is_verified": false, - "line_number": 101, + "line_number": 100, "type": "Secret Keyword" }, { "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "is_secret": false, "is_verified": false, - "line_number": 110, + "line_number": 109, "type": "Secret Keyword" }, { "hashed_secret": "fa4497447699cdb0a81c66a7f21af28a75170195", "is_secret": false, "is_verified": false, - "line_number": 112, + "line_number": 111, "type": "Secret Keyword" } ], @@ -797,30 +629,16 @@ "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "is_secret": false, "is_verified": false, - "line_number": 240, + "line_number": 243, "type": "Secret Keyword" } ], "helm/sower/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 36, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 51, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 53, + "line_number": 52, "type": "Secret Keyword" } ], @@ -834,32 +652,18 @@ } ], "helm/ssjdispatcher/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 40, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 57, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 59, + "line_number": 58, "type": "Secret Keyword" }, { "hashed_secret": "0c86d58792b32e1d12af733a0614837ff9002014", "is_secret": false, "is_verified": false, - "line_number": 114, + "line_number": 113, "type": "Secret Keyword" } ], @@ -877,37 +681,23 @@ "hashed_secret": "13d9ed7e3d69f1b6330dff80bc4658931708eddc", "is_secret": false, "is_verified": false, - "line_number": 215, + "line_number": 218, "type": "Secret Keyword" } ], "helm/wts/README.md": [ - { - "hashed_secret": "8a10cd156f8f43ec303f885a7985b1cf90635e23", - "is_secret": false, - "is_verified": false, - "line_number": 32, - "type": "Secret Keyword" - }, - { - "hashed_secret": "2546383b95bb44732e9be6a877fd476c0442fdab", - "is_secret": false, - "is_verified": false, - "line_number": 52, - "type": "Secret Keyword" - }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 54, + "line_number": 53, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 75, + "line_number": 74, "type": "Secret Keyword" } ], diff --git a/helm/ambassador/README.md b/helm/ambassador/README.md index 06e4b0e2..e6489c31 100644 --- a/helm/ambassador/README.md +++ b/helm/ambassador/README.md @@ -26,7 +26,6 @@ A Helm chart for deploying ambassador for gen3 | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | fullnameOverride | string | `"ambassador-deployment"` | Override the full name of the deployment. | -| global | map | `{"ddEnabled":false,"environment":"default","minAvialable":1,"pdb":false}` | Global configuration options. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.minAvialable | int | `1` | The minimum amount of pods that are available at all times if the PDB is deployed. | diff --git a/helm/ambassador/values.yaml b/helm/ambassador/values.yaml index f3f6be41..0a78ca53 100644 --- a/helm/ambassador/values.yaml +++ b/helm/ambassador/values.yaml @@ -1,8 +1,7 @@ # Default values for ambassador. # This is a YAML-formatted file. # Declare variables to be passed into your templates. - -# -- (map) Global configuration options. +# Global configuration global: # -- (string) Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. environment: default diff --git a/helm/arborist/README.md b/helm/arborist/README.md index 7df700a8..d5914a34 100644 --- a/helm/arborist/README.md +++ b/helm/arborist/README.md @@ -28,10 +28,9 @@ A Helm chart for gen3 arborist | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"JWKS_ENDPOINT","value":"http://fence-service/.well-known/jwks"}]` | Environment variables to pass to the container | | env[0] | string | `{"name":"JWKS_ENDPOINT","value":"http://fence-service/.well-known/jwks"}` | The URL of the JSON Web Key Set (JWKS) endpoint for authentication | -| externalSecrets | map | `{"arboristSmDbcreds":null}` | External Secrets settings. | -| externalSecrets.arboristSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | +| externalSecrets | map | `{"dbcreds":null}` | External Secrets settings. | +| externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -39,7 +38,7 @@ A Helm chart for gen3 arborist | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any arborist secrets you have deployed. | @@ -51,8 +50,8 @@ A Helm chart for gen3 arborist | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/arborist/templates/_helpers.tpl b/helm/arborist/templates/_helpers.tpl index 1dfea5b1..9a85f4bd 100644 --- a/helm/arborist/templates/_helpers.tpl +++ b/helm/arborist/templates/_helpers.tpl @@ -79,24 +79,3 @@ Create the name of the service account to use {{- end }} {{- end }} -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} - {{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} - -{{/* - Service DB Creds Secrets Manager Name -*/}} -{{- define "arborist-sm-dbcreds" -}} -{{- if .Values.externalSecrets.arboristSmDbcreds }} - {{- default .Values.externalSecrets.arboristSmDbcreds }} -{{- else }} - {{- .Values.global.environment }}- {{- .Chart.Name }}-creds -{{- end -}} -{{- end -}} diff --git a/helm/arborist/templates/db-init.yaml b/helm/arborist/templates/db-init.yaml index abbefb6e..6738ad76 100644 --- a/helm/arborist/templates/db-init.yaml +++ b/helm/arborist/templates/db-init.yaml @@ -1,5 +1,6 @@ -{{ include "common.db_setup_job" . }} ---- +{{- if not .Values.global.externalSecrets.deploy }} +{{ include "common.db-secret" . }} +{{- end }} {{ include "common.db-secret" . }} --- {{ include "common.db_setup_sa" . }} diff --git a/helm/arborist/templates/external-secret.yaml b/helm/arborist/templates/external-secret.yaml index 42ca56e0..70c278fe 100644 --- a/helm/arborist/templates/external-secret.yaml +++ b/helm/arborist/templates/external-secret.yaml @@ -1,19 +1 @@ -{{ if .Values.global.externalSecrets.deploy }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ $.Chart.Name }}-dbcreds -spec: - refreshInterval: 5m - secretStoreRef: - name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore - target: - name: {{ $.Chart.Name }}-dbcreds - creationPolicy: Owner - data: - - secretKey: data - remoteRef: - #name of secret in secrets manager - key: {{include "arborist-sm-dbcreds" .}} -{{- end }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/arborist/values.yaml b/helm/arborist/values.yaml index 0ca7ff07..fd9091f4 100644 --- a/helm/arborist/values.yaml +++ b/helm/arborist/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -49,7 +52,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. @@ -66,7 +69,7 @@ global: # -- (map) External Secrets settings. externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" - arboristSmDbcreds: + dbcreds: # -- (map) Secret information for External Secrets. secrets: # -- (str) AWS access key ID. Overrides global key. diff --git a/helm/argo-wrapper/README.md b/helm/argo-wrapper/README.md index b5f7b3a1..29f396e2 100644 --- a/helm/argo-wrapper/README.md +++ b/helm/argo-wrapper/README.md @@ -32,7 +32,6 @@ A Helm chart for gen3 Argo Wrapper Service | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | environment | string | `"default"` | Environment name. | -| global | map | `{"ddEnabled":false,"environment":"default","minAvialable":1,"pdb":false}` | Global configuration options. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.minAvialable | int | `1` | The minimum amount of pods that are available at all times if the PDB is deployed. | diff --git a/helm/argo-wrapper/values.yaml b/helm/argo-wrapper/values.yaml index 47c711b0..e98ca8a7 100644 --- a/helm/argo-wrapper/values.yaml +++ b/helm/argo-wrapper/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (string) Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. environment: default diff --git a/helm/audit/README.md b/helm/audit/README.md index 49ec0eca..760da3c9 100644 --- a/helm/audit/README.md +++ b/helm/audit/README.md @@ -36,11 +36,10 @@ A Helm chart for Kubernetes | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"DEBUG","value":"false"},{"name":"ARBORIST_URL","valueFrom":{"configMapKeyRef":{"key":"arborist_url","name":"manifest-global","optional":true}}}]` | Environment variables to pass to the container | -| externalSecrets | map | `{"auditG3auto":null,"auditSmDbcreds":null}` | External Secrets settings. | +| externalSecrets | map | `{"auditG3auto":null,"dbcreds":null}` | External Secrets settings. | | externalSecrets.auditG3auto | string | `nil` | Will override the name of the aws secrets manager secret. Default is "audit-g3auto" | -| externalSecrets.auditSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | +| externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the chart, which is used as the name of resources created by the chart | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -48,7 +47,7 @@ A Helm chart for Kubernetes | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any audit secrets you have deployed. | @@ -60,8 +59,8 @@ A Helm chart for Kubernetes | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/audit/templates/_helpers.tpl b/helm/audit/templates/_helpers.tpl index 08700261..ee0e4c3f 100644 --- a/helm/audit/templates/_helpers.tpl +++ b/helm/audit/templates/_helpers.tpl @@ -97,13 +97,3 @@ Create the name of the service account to use {{- default "audit-g3auto" .Values.externalSecrets.auditG3auto }} {{- end }} -{{/* - Service DB Creds Secrets Manager Name -*/}} -{{- define "audit-sm-dbcreds" -}} -{{- if .Values.externalSecrets.auditSmDbcreds }} - {{- default .Values.externalSecrets.auditSmDbcreds }} -{{- else }} - {{- .Values.global.environment }}- {{- .Chart.Name }}-creds -{{- end -}} -{{- end -}} diff --git a/helm/audit/templates/db-init.yaml b/helm/audit/templates/db-init.yaml index 50bd8e8f..f691b8e9 100644 --- a/helm/audit/templates/db-init.yaml +++ b/helm/audit/templates/db-init.yaml @@ -1,5 +1,6 @@ -{{ include "common.db_setup_job" . }} ---- +{{- if not .Values.global.externalSecrets.deploy }} +{{ include "common.db-secret" . }} +{{- end }} {{ include "common.db-secret" . }} --- {{ include "common.db_setup_sa" . }} diff --git a/helm/audit/templates/external-secret.yaml b/helm/audit/templates/external-secret.yaml index fca176ac..6302b3d2 100644 --- a/helm/audit/templates/external-secret.yaml +++ b/helm/audit/templates/external-secret.yaml @@ -16,22 +16,6 @@ spec: remoteRef: #name of secret in secrets manager key: {{include "audit-g3auto" .}} +{{- end }} --- -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ $.Chart.Name }}-dbcreds -spec: - refreshInterval: 5m - secretStoreRef: - name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore - target: - name: {{ $.Chart.Name }}-dbcreds - creationPolicy: Owner - data: - - secretKey: data - remoteRef: - #name of secret in secrets manager - key: {{include "audit-sm-dbcreds" .}} -{{- end }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/audit/values.yaml b/helm/audit/values.yaml index b8b31d23..fe372d8a 100644 --- a/helm/audit/values.yaml +++ b/helm/audit/values.yaml @@ -1,7 +1,8 @@ # Default values for audit. # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -13,10 +14,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -48,7 +51,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. @@ -67,7 +70,7 @@ externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "audit-g3auto" auditG3auto: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" - auditSmDbcreds: + dbcreds: # -- (map) Secret information for External Secrets. secrets: # -- (str) AWS access key ID. Overrides global key. diff --git a/helm/aws-es-proxy/README.md b/helm/aws-es-proxy/README.md index 7ddd2bfc..3c0e30b7 100644 --- a/helm/aws-es-proxy/README.md +++ b/helm/aws-es-proxy/README.md @@ -26,7 +26,6 @@ A Helm chart for AWS ES Proxy Service for gen3 | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | esEndpoint | str | `"test.us-east-1.es.amazonaws.com"` | Elasticsearch endpoint in AWS | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"environment":"default","minAvialable":1,"pdb":false}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | diff --git a/helm/aws-es-proxy/values.yaml b/helm/aws-es-proxy/values.yaml index e2f11aee..1666f771 100644 --- a/helm/aws-es-proxy/values.yaml +++ b/helm/aws-es-proxy/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: diff --git a/helm/common/README.md b/helm/common/README.md index a93a01fa..72b9bd35 100644 --- a/helm/common/README.md +++ b/helm/common/README.md @@ -8,19 +8,18 @@ A Helm chart for provisioning databases in gen3 | Key | Type | Default | Description | |-----|------|---------|-------------| -| global | map | `{"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","netPolicy":true,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/common/templates/_db_setup_job.tpl b/helm/common/templates/_db_setup_job.tpl index 7acd75bb..f48decb9 100644 --- a/helm/common/templates/_db_setup_job.tpl +++ b/helm/common/templates/_db_setup_job.tpl @@ -58,16 +58,44 @@ spec: name: {{ .Release.Name }}-postgresql key: postgres-password optional: false + {{- else if $.Values.global.postgres.externalSecret }} + valueFrom: + secretKeyRef: + name: {{ $.Values.global.postgres.externalSecret }} + key: password + optional: false {{- else }} value: {{ .Values.global.postgres.master.password | quote}} {{- end }} - name: PGUSER + {{- if $.Values.global.postgres.externalSecret }} + valueFrom: + secretKeyRef: + name: {{ $.Values.global.postgres.externalSecret }} + key: username + optional: false + {{- else }} value: {{ .Values.global.postgres.master.username | quote }} + {{- end }} - name: PGPORT + {{- if $.Values.global.postgres.externalSecret }} + valueFrom: + secretKeyRef: + name: {{ $.Values.global.postgres.externalSecret }} + key: port + optional: false + {{- else }} value: {{ .Values.global.postgres.master.port | quote }} + {{- end }} - name: PGHOST {{- if $.Values.global.dev }} value: "{{ .Release.Name }}-postgresql" + {{- else if $.Values.global.postgres.externalSecret }} + valueFrom: + secretKeyRef: + name: {{ $.Values.global.postgres.externalSecret }} + key: host + optional: false {{- else }} value: {{ .Values.global.postgres.master.host | quote }} {{- end }} @@ -140,6 +168,7 @@ Create k8s secrets for connecting to postgres */}} # DB Secrets {{- define "common.db-secret" -}} +{{- if not .Values.global.externalSecrets.deploy }} apiVersion: v1 kind: Secret metadata: @@ -154,4 +183,5 @@ data: {{- else }} host: {{ ( $.Values.postgres.host | default ( $.Values.global.postgres.master.host)) | b64enc | quote }} {{- end }} +{{- end }} {{- end }} \ No newline at end of file diff --git a/helm/common/templates/_external_secrets.tpl b/helm/common/templates/_external_secrets.tpl new file mode 100644 index 00000000..fd8f402e --- /dev/null +++ b/helm/common/templates/_external_secrets.tpl @@ -0,0 +1,36 @@ +{{/* + Service DB Creds Secrets Manager Name +*/}} +{{- define "common.externalSecret.dbcreds.name" -}} +{{- if .Values.externalSecrets.dbcreds }} + {{- default .Values.externalSecrets.dbcreds }} +{{- else }} + {{- .Values.global.environment }}- {{- .Chart.Name }}-creds +{{- end -}} +{{- end -}} + + +{{/* + ExternalSecrets Object +*/}} +{{- define "common.externalSecret.db" -}} +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ $.Chart.Name }}-dbcreds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: {{ $.Chart.Name }}-dbcreds + creationPolicy: Owner + dataFrom: + - extract: + key: {{include "common.externalSecret.dbcreds.name" .}} + conversionStrategy: Default + decodingStrategy: None +{{- end }} +{{- end -}} diff --git a/helm/common/values.yaml b/helm/common/values.yaml index d61b0b39..3d3d2297 100644 --- a/helm/common/values.yaml +++ b/helm/common/values.yaml @@ -2,14 +2,17 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -41,6 +44,6 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false diff --git a/helm/dicom-server/README.md b/helm/dicom-server/README.md index fd8c52f9..a1a11814 100644 --- a/helm/dicom-server/README.md +++ b/helm/dicom-server/README.md @@ -24,7 +24,6 @@ A Helm chart for gen3 Dicom Server | datadogLogsInjection | bool | `true` | If enabled, the Datadog Agent will automatically inject Datadog-specific metadata into your application logs. | | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | -| global | map | `{"ddEnabled":false,"environment":"default","minAvialable":1,"pdb":false}` | Global configuration options. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.minAvialable | int | `1` | The minimum amount of pods that are available at all times if the PDB is deployed. | diff --git a/helm/dicom-server/values.yaml b/helm/dicom-server/values.yaml index d4dcdcc7..3cf06900 100644 --- a/helm/dicom-server/values.yaml +++ b/helm/dicom-server/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (string) Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. environment: default diff --git a/helm/dicom-viewer/README.md b/helm/dicom-viewer/README.md index 78ea3e63..d2bb751c 100644 --- a/helm/dicom-viewer/README.md +++ b/helm/dicom-viewer/README.md @@ -24,7 +24,6 @@ A Helm chart for gen3 Dicom Viewer | datadogLogsInjection | bool | `true` | If enabled, the Datadog Agent will automatically inject Datadog-specific metadata into your application logs. | | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | -| global | map | `{"ddEnabled":false,"environment":"default","minAvialable":1,"pdb":false}` | Global configuration options. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.minAvialable | int | `1` | The minimum amount of pods that are available at all times if the PDB is deployed. | diff --git a/helm/dicom-viewer/values.yaml b/helm/dicom-viewer/values.yaml index 0fa31147..01c3995b 100644 --- a/helm/dicom-viewer/values.yaml +++ b/helm/dicom-viewer/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (string) Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. environment: default diff --git a/helm/elasticsearch/README.md b/helm/elasticsearch/README.md index 132f8fa7..2a3e7758 100644 --- a/helm/elasticsearch/README.md +++ b/helm/elasticsearch/README.md @@ -25,7 +25,6 @@ A Helm chart for Kubernetes | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | fullnameOverride | string | `""` | | -| global | map | `{"ddEnabled":false,"environment":"default"}` | Global configuration options. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | image.pullPolicy | string | `"IfNotPresent"` | | diff --git a/helm/elasticsearch/values.yaml b/helm/elasticsearch/values.yaml index 2f06d61e..7188c66b 100644 --- a/helm/elasticsearch/values.yaml +++ b/helm/elasticsearch/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (string) Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. environment: default diff --git a/helm/fence/README.md b/helm/fence/README.md index 09a300ce..6456cf28 100644 --- a/helm/fence/README.md +++ b/helm/fence/README.md @@ -89,14 +89,13 @@ A Helm chart for gen3 Fence | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"GEN3_UWSGI_TIMEOUT","valueFrom":{"configMapKeyRef":{"key":"uwsgi-timeout","name":"manifest-global","optional":true}}},{"name":"DD_AGENT_HOST","valueFrom":{"fieldRef":{"fieldPath":"status.hostIP"}}},{"name":"AWS_STS_REGIONAL_ENDPOINTS","value":"regional"},{"name":"PYTHONPATH","value":"/var/www/fence"},{"name":"GEN3_DEBUG","value":"False"},{"name":"FENCE_PUBLIC_CONFIG","valueFrom":{"configMapKeyRef":{"key":"fence-config-public.yaml","name":"manifest-fence","optional":true}}},{"name":"PGHOST","valueFrom":{"secretKeyRef":{"key":"host","name":"fence-dbcreds","optional":false}}},{"name":"PGUSER","valueFrom":{"secretKeyRef":{"key":"username","name":"fence-dbcreds","optional":false}}},{"name":"PGPASSWORD","valueFrom":{"secretKeyRef":{"key":"password","name":"fence-dbcreds","optional":false}}},{"name":"PGDB","valueFrom":{"secretKeyRef":{"key":"database","name":"fence-dbcreds","optional":false}}},{"name":"DBREADY","valueFrom":{"secretKeyRef":{"key":"dbcreated","name":"fence-dbcreds","optional":false}}},{"name":"DB","value":"postgresql://$(PGUSER):$(PGPASSWORD)@$(PGHOST):5432/$(PGDB)"},{"name":"INDEXD_PASSWORD","valueFrom":{"secretKeyRef":{"key":"fence","name":"indexd-service-creds"}}},{"name":"gen3Env","valueFrom":{"configMapKeyRef":{"key":"hostname","name":"manifest-global"}}}]` | Environment variables to pass to the container | -| externalSecrets | map | `{"fenceConfig":null,"fenceGoogleAppCredsSecret":null,"fenceGoogleStorageCredsSecret":null,"fenceJwtKeys":null,"fenceSmDbcreds":null}` | External Secrets settings. | +| externalSecrets | map | `{"dbcreds":null,"fenceConfig":null,"fenceGoogleAppCredsSecret":null,"fenceGoogleStorageCredsSecret":null,"fenceJwtKeys":null}` | External Secrets settings. | +| externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | externalSecrets.fenceConfig | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-config" | | externalSecrets.fenceGoogleAppCredsSecret | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-google-app-creds-secret" | | externalSecrets.fenceGoogleStorageCredsSecret | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-google-storage-creds-secret" | | externalSecrets.fenceJwtKeys | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-jwt-keys" | -| externalSecrets.fenceSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false,"useLocalSecret":{"enabled":false,"localSecretName":null,"localSecretNamespace":null}},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","syncFromDbgap":false,"tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false,"useLocalSecret":{"enabled":false,"localSecretName":null,"localSecretNamespace":null}}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -108,7 +107,7 @@ A Helm chart for gen3 Fence | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any fence secrets you have deployed. | @@ -120,8 +119,8 @@ A Helm chart for gen3 Fence | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | @@ -131,7 +130,7 @@ A Helm chart for gen3 Fence | global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | ARN of the reverse proxy certificate. | | global.syncFromDbgap | bool | `false` | Whether to sync data from dbGaP. | | global.tierAccessLevel | string | `"libre"` | Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` | -| global.tierAccessLimit | int | `1000` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | +| global.tierAccessLimit | int | `"1000"` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | | image.pullPolicy | string | `"Always"` | When to pull the image. This value should be "Always" to ensure the latest image is used. | | image.repository | string | `"quay.io/cdis/fence"` | The Docker image repository for the fence service | | image.tag | string | `"master"` | Overrides the image tag whose default is the chart appVersion. | diff --git a/helm/fence/templates/db-init.yaml b/helm/fence/templates/db-init.yaml index abbefb6e..6738ad76 100644 --- a/helm/fence/templates/db-init.yaml +++ b/helm/fence/templates/db-init.yaml @@ -1,5 +1,6 @@ -{{ include "common.db_setup_job" . }} ---- +{{- if not .Values.global.externalSecrets.deploy }} +{{ include "common.db-secret" . }} +{{- end }} {{ include "common.db-secret" . }} --- {{ include "common.db_setup_sa" . }} diff --git a/helm/fence/templates/external-secret.yaml b/helm/fence/templates/external-secret.yaml index ece35301..b5115387 100644 --- a/helm/fence/templates/external-secret.yaml +++ b/helm/fence/templates/external-secret.yaml @@ -70,22 +70,6 @@ spec: remoteRef: #name of secret in secrets manager key: {{include "fence-config" .}} +{{- end }} --- -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ $.Chart.Name }}-dbcreds -spec: - refreshInterval: 5m - secretStoreRef: - name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore - target: - name: {{ $.Chart.Name }}-dbcreds - creationPolicy: Owner - data: - - secretKey: data - remoteRef: - #name of secret in secrets manager - key: {{include "fence-sm-dbcreds" .}} -{{- end }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/fence/values.yaml b/helm/fence/values.yaml index 300fd24a..ec8defd8 100644 --- a/helm/fence/values.yaml +++ b/helm/fence/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -22,10 +23,12 @@ global: localSecretNamespace: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -57,11 +60,11 @@ global: # -- (string) Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` tierAccessLevel: libre # -- (int) Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. - tierAccessLimit: 1000 + tierAccessLimit: "1000" # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. @@ -86,7 +89,7 @@ externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "fence-config" fenceConfig: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" - fenceSmDbcreds: + dbcreds: # -- (map) Configuration options for usersync cronjob. usersync: diff --git a/helm/gen3/README.md b/helm/gen3/README.md index c1cbb407..c4e2f8c8 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -96,7 +96,7 @@ Helm chart to deploy Gen3 Data Commons | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Deploys postgres/elasticsearch for dev | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces in same cluster. | | global.externalSecrets | map | `{"deploy":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override secrets you have deployed. | @@ -111,7 +111,7 @@ Helm chart to deploy Gen3 Data Commons | global.publicDataSets | bool | `true` | Whether public datasets are enabled. | | global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | ARN of the reverse proxy certificate. | | global.tierAccessLevel | string | `"libre"` | Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` | -| global.tierAccessLimit | int | `1000` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | +| global.tierAccessLimit | int | `"1000"` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | | guppy.enabled | bool | `false` | Whether to deploy the guppy subchart. | | guppy.image | map | `{"repository":null,"tag":null}` | Docker image information. | | guppy.image.repository | string | `nil` | The Docker image repository for the guppy service. | diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index 7c0c0839..ba1b08f2 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -2,6 +2,7 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. +# Global configuration global: # -- (map) AWS configuration aws: @@ -50,11 +51,11 @@ global: # -- (string) Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` tierAccessLevel: libre # -- (int) Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. - tierAccessLimit: 1000 + tierAccessLimit: "1000" # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (map) External Secrets settings. diff --git a/helm/guppy/README.md b/helm/guppy/README.md index f8c99a11..b40f3744 100644 --- a/helm/guppy/README.md +++ b/helm/guppy/README.md @@ -40,7 +40,6 @@ A Helm chart for gen3 Guppy Service | enableEncryptWhitelist | bool | `true` | Whether or not to enable encryption for specified fields | | encryptWhitelist | string | `"test1"` | A comma-separated list of fields to encrypt | | esEndpoint | string | `""` | Elasticsearch endpoint. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -48,7 +47,7 @@ A Helm chart for gen3 Guppy Service | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | @@ -57,8 +56,8 @@ A Helm chart for gen3 Guppy Service | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | @@ -67,7 +66,7 @@ A Helm chart for gen3 Guppy Service | global.publicDataSets | bool | `true` | Whether public datasets are enabled. | | global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | ARN of the reverse proxy certificate. | | global.tierAccessLevel | string | `"libre"` | Access level for tiers. | -| global.tierAccessLimit | int | `1000` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | +| global.tierAccessLimit | int | `"1000"` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | | image | map | `{"pullPolicy":"Always","repository":"quay.io/cdis/guppy","tag":""}` | Docker image information. | | image.pullPolicy | string | `"Always"` | Docker pull policy. | | image.repository | string | `"quay.io/cdis/guppy"` | Docker repository. | diff --git a/helm/guppy/values.yaml b/helm/guppy/values.yaml index fafd7c37..f744257f 100644 --- a/helm/guppy/values.yaml +++ b/helm/guppy/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -47,11 +50,11 @@ global: # -- (string) Access level for tiers. tierAccessLevel: libre # -- (int) Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. - tierAccessLimit: 1000 + tierAccessLimit: "1000" # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. diff --git a/helm/hatchery/README.md b/helm/hatchery/README.md index 4e7bfe3c..40ce0d73 100644 --- a/helm/hatchery/README.md +++ b/helm/hatchery/README.md @@ -27,7 +27,6 @@ A Helm chart for gen3 Hatchery | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"HTTP_PORT","value":"8000"},{"name":"POD_NAMESPACE","valueFrom":{"fieldRef":{"fieldPath":"metadata.namespace"}}}]` | Environment variables to pass to the container | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -35,7 +34,7 @@ A Helm chart for gen3 Hatchery | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | @@ -44,8 +43,8 @@ A Helm chart for gen3 Hatchery | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/hatchery/values.yaml b/helm/hatchery/values.yaml index 27127335..739f9457 100644 --- a/helm/hatchery/values.yaml +++ b/helm/hatchery/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -49,7 +52,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. diff --git a/helm/indexd/README.md b/helm/indexd/README.md index 3c037814..e7698753 100644 --- a/helm/indexd/README.md +++ b/helm/indexd/README.md @@ -27,10 +27,9 @@ A Helm chart for gen3 indexd | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | defaultPrefix | string | `"PREFIX/"` | default prefix for indexd | | env | list | `[{"name":"ARBORIST","value":"true"},{"name":"GEN3_DEBUG","value":"False"}]` | Environment variables to pass to the container | -| externalSecrets | map | `{"indexdSmDbcreds":null}` | External Secrets settings. | -| externalSecrets.indexdSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | +| externalSecrets | map | `{"dbcreds":null}` | External Secrets settings. | +| externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -38,7 +37,7 @@ A Helm chart for gen3 indexd | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any indexd secrets you have deployed. | @@ -50,8 +49,8 @@ A Helm chart for gen3 indexd | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | @@ -60,7 +59,7 @@ A Helm chart for gen3 indexd | global.publicDataSets | bool | `true` | Whether public datasets are enabled. | | global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | ARN of the reverse proxy certificate. | | global.tierAccessLevel | string | `"libre"` | Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` | -| global.tierAccessLimit | int | `1000` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | +| global.tierAccessLimit | int | `"1000"` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | | image | map | `{"pullPolicy":"IfNotPresent","repository":"quay.io/cdis/indexd","tag":""}` | Docker image information. | | image.pullPolicy | string | `"IfNotPresent"` | When to pull the image. | | image.repository | string | `"quay.io/cdis/indexd"` | The Docker image repository for the indexd service | diff --git a/helm/indexd/templates/_helpers.tpl b/helm/indexd/templates/_helpers.tpl index 21635df6..0c6704b6 100644 --- a/helm/indexd/templates/_helpers.tpl +++ b/helm/indexd/templates/_helpers.tpl @@ -113,14 +113,3 @@ Create the name of the service account to use {{- default "gen3-secret-store"}} {{- end -}} {{- end -}} - -{{/* - Service DB Creds Secrets Manager Name -*/}} -{{- define "indexd-sm-dbcreds" -}} -{{- if .Values.externalSecrets.indexdSmDbcreds }} - {{- default .Values.externalSecrets.indexdSmDbcreds }} -{{- else }} - {{- .Values.global.environment }}- {{- .Chart.Name }}-creds -{{- end -}} -{{- end -}} diff --git a/helm/indexd/templates/db-init.yaml b/helm/indexd/templates/db-init.yaml index 0393aa73..d25e1779 100644 --- a/helm/indexd/templates/db-init.yaml +++ b/helm/indexd/templates/db-init.yaml @@ -1,4 +1,6 @@ +{{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} +{{- end }} --- {{ include "common.db_setup_sa" . }} --- diff --git a/helm/indexd/templates/external-secrets.yaml b/helm/indexd/templates/external-secrets.yaml index 7a00916f..70c278fe 100644 --- a/helm/indexd/templates/external-secrets.yaml +++ b/helm/indexd/templates/external-secrets.yaml @@ -1,19 +1 @@ -{{ if .Values.global.externalSecrets.deploy }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ $.Chart.Name }}-dbcreds -spec: - refreshInterval: 5m - secretStoreRef: - name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore - target: - name: {{ $.Chart.Name }}-dbcreds - creationPolicy: Owner - data: - - secretKey: data - remoteRef: - #name of secret in secrets manager - key: {{include "indexd-sm-dbcreds" .}} -{{- end }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/indexd/values.yaml b/helm/indexd/values.yaml index c2302ec0..ec9379bb 100644 --- a/helm/indexd/values.yaml +++ b/helm/indexd/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -47,11 +50,11 @@ global: # -- (string) Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` tierAccessLevel: libre # -- (int) Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. - tierAccessLimit: 1000 + tierAccessLimit: "1000" # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. @@ -68,7 +71,7 @@ global: # -- (map) External Secrets settings. externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" - indexdSmDbcreds: + dbcreds: # -- (map) Values for indexd secret. secrets: diff --git a/helm/manifestservice/README.md b/helm/manifestservice/README.md index ad10c8c8..c7294538 100644 --- a/helm/manifestservice/README.md +++ b/helm/manifestservice/README.md @@ -35,7 +35,6 @@ A Helm chart for Kubernetes | env | list | `[{"name":"REQUESTS_CA_BUNDLE","value":"/etc/ssl/certs/ca-certificates.crt"},{"name":"MANIFEST_SERVICE_CONFIG_PATH","value":"/var/gen3/config/config.json"},{"name":"GEN3_DEBUG","value":"False"}]` | Environment variables to pass to the container | | externalSecrets | map | `{"manifestserviceG3auto":null}` | External Secrets settings. | | externalSecrets.manifestserviceG3auto | string | `nil` | Will override the name of the aws secrets manager secret. Default is "manifestservice-g3auto" | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"minAvialable":1,"pdb":false}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | diff --git a/helm/manifestservice/values.yaml b/helm/manifestservice/values.yaml index 4d1d0f67..ad768455 100644 --- a/helm/manifestservice/values.yaml +++ b/helm/manifestservice/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: diff --git a/helm/metadata/README.md b/helm/metadata/README.md index 8e115391..157751bf 100644 --- a/helm/metadata/README.md +++ b/helm/metadata/README.md @@ -38,9 +38,8 @@ A Helm chart for gen3 Metadata Service | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | debug | bool | `false` | | | esEndpoint | string | `"elasticsearch:9200"` | Elasticsearch endpoint. | -| externalSecrets | map | `{"metadataSmDbcreds":null}` | External Secrets settings. | -| externalSecrets.metadataSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | +| externalSecrets | map | `{"dbcreds":null}` | External Secrets settings. | +| externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -48,7 +47,7 @@ A Helm chart for gen3 Metadata Service | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any metadata secrets you have deployed. | @@ -60,8 +59,8 @@ A Helm chart for gen3 Metadata Service | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/metadata/templates/_helpers.tpl b/helm/metadata/templates/_helpers.tpl index ef1edcef..f8424983 100644 --- a/helm/metadata/templates/_helpers.tpl +++ b/helm/metadata/templates/_helpers.tpl @@ -77,25 +77,3 @@ Create the name of the service account to use {{- default .Values.postgres.password }} {{- end }} {{- end }} - -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} - {{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} - -{{/* - Service DB Creds Secrets Manager Name -*/}} -{{- define "metadata-sm-dbcreds" -}} -{{- if .Values.externalSecrets.metadataSmDbcreds }} - {{- default .Values.externalSecrets.metadataSmDbcreds }} -{{- else }} - {{- .Values.global.environment }}- {{- .Chart.Name }}-creds -{{- end -}} -{{- end -}} diff --git a/helm/metadata/templates/external-secret.yaml b/helm/metadata/templates/external-secret.yaml index 478d262e..70c278fe 100644 --- a/helm/metadata/templates/external-secret.yaml +++ b/helm/metadata/templates/external-secret.yaml @@ -1,19 +1 @@ -{{ if .Values.global.externalSecrets.deploy }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ $.Chart.Name }}-dbcreds -spec: - refreshInterval: 5m - secretStoreRef: - name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore - target: - name: {{ $.Chart.Name }}-dbcreds - creationPolicy: Owner - data: - - secretKey: data - remoteRef: - #name of secret in secrets manager - key: {{include "metadata-sm-dbcreds" .}} -{{- end }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/metadata/values.yaml b/helm/metadata/values.yaml index cfdb6fd0..0f9c6d7d 100644 --- a/helm/metadata/values.yaml +++ b/helm/metadata/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -49,7 +52,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. @@ -66,7 +69,7 @@ global: # -- (map) External Secrets settings. externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" - metadataSmDbcreds: + dbcreds: # -- (map) Secret information to access the db restore job S3 bucket. secrets: # -- (str) AWS access key ID. Overrides global key. diff --git a/helm/peregrine/README.md b/helm/peregrine/README.md index 6f9f8c7b..891b516b 100644 --- a/helm/peregrine/README.md +++ b/helm/peregrine/README.md @@ -28,10 +28,9 @@ A Helm chart for gen3 Peregrine service | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `nil` | Environment variables to pass to the container | -| externalSecrets | map | `{"peregrineSmDbcreds":null}` | External Secrets settings. | -| externalSecrets.peregrineSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | +| externalSecrets | map | `{"dbcreds":null}` | External Secrets settings. | +| externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -39,7 +38,7 @@ A Helm chart for gen3 Peregrine service | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any peregrine secrets you have deployed. | @@ -51,8 +50,8 @@ A Helm chart for gen3 Peregrine service | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/peregrine/templates/db-init.yaml b/helm/peregrine/templates/db-init.yaml index abbefb6e..6738ad76 100644 --- a/helm/peregrine/templates/db-init.yaml +++ b/helm/peregrine/templates/db-init.yaml @@ -1,5 +1,6 @@ -{{ include "common.db_setup_job" . }} ---- +{{- if not .Values.global.externalSecrets.deploy }} +{{ include "common.db-secret" . }} +{{- end }} {{ include "common.db-secret" . }} --- {{ include "common.db_setup_sa" . }} diff --git a/helm/peregrine/templates/external-secret.yaml b/helm/peregrine/templates/external-secret.yaml index 92cfab01..70c278fe 100644 --- a/helm/peregrine/templates/external-secret.yaml +++ b/helm/peregrine/templates/external-secret.yaml @@ -1,19 +1 @@ -{{ if .Values.global.externalSecrets.deploy }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ $.Chart.Name }}-dbcreds -spec: - refreshInterval: 5m - secretStoreRef: - name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore - target: - name: {{ $.Chart.Name }}-dbcreds - creationPolicy: Owner - data: - - secretKey: data - remoteRef: - #name of secret in secrets manager - key: {{include "peregrine-sm-dbcreds" .}} -{{- end }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/peregrine/values.yaml b/helm/peregrine/values.yaml index bca29606..58553889 100644 --- a/helm/peregrine/values.yaml +++ b/helm/peregrine/values.yaml @@ -1,7 +1,8 @@ # Default values for peregrine. # This is a YAML-formatted file. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -13,10 +14,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -46,7 +49,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. @@ -63,7 +66,7 @@ global: # -- (map) External Secrets settings. externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" - peregrineSmDbcreds: + dbcreds: # -- (map) Secret information for External Secrets. secrets: # -- (str) AWS access key ID. Overrides global key. diff --git a/helm/pidgin/README.md b/helm/pidgin/README.md index 72b5f9bc..3172a0fc 100644 --- a/helm/pidgin/README.md +++ b/helm/pidgin/README.md @@ -33,7 +33,6 @@ A Helm chart for gen3 Pidgin Service | datadogLogsInjection | bool | `true` | If enabled, the Datadog Agent will automatically inject Datadog-specific metadata into your application logs. | | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -41,7 +40,7 @@ A Helm chart for gen3 Pidgin Service | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | @@ -50,8 +49,8 @@ A Helm chart for gen3 Pidgin Service | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/pidgin/values.yaml b/helm/pidgin/values.yaml index fb683716..414d642b 100644 --- a/helm/pidgin/values.yaml +++ b/helm/pidgin/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -49,7 +52,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. diff --git a/helm/portal/README.md b/helm/portal/README.md index a1287bff..acccd3e1 100644 --- a/helm/portal/README.md +++ b/helm/portal/README.md @@ -39,7 +39,6 @@ A Helm chart for gen3 data-portal | gitops.favicon | string | `"AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQv3IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1MiCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwKg0Nd6yqf+8pi7D3rKp/96yqf/esqn/3rKp/76qNMPEpU2QxbFJNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/7WfF3cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMWySQAAAAAA3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/TrIS0AAAAAL+nLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACxmAIAxrhKBregGtLesqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/2MyPCLGaCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs5kJANqvn0vesqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/18l+GwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKuSAADq5L8H3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/z79qBca0SwAAAAAAAAAAAAAAAAAAAAAAAAAAAN6yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf+4oR3YAAAAAAAAAAAAAAAAAAAAAAAAAAC4oBlZ3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/AqC/N3rKp/96yqf+/rD3M3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf+4oyBkAAAAAAAAAAAAAAAAAAAAAN6yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf+9qDAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzb1oH96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/8qoYv8AAAAAAAAAALefHQC4oB5X3rKp/96yqf/esqn/AAAAAAAAAADm3bsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOHbrAAAAAAA6ePTEd6yqf/esqn/3rKp/8CsNngAAAAAAAAAAN6yqf/esqn/3rKp/////xIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADq4bwA08V3EN6yqf/esqn/3rKp/wAAAAAAAAAA3rKp/96yqf+6nyfZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3rKp/96yqf/esqn/AAAAALyjJDbesqn/3rKp/7ihIc0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADFpE7l3rKp/96yqf/esqn/wq0+Wd6yqf/esqn/3rKp/wAAAADPwW4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7pCAAAAAAAN6yqf/esqn/3rKp/8CsOVK6oyF63rKp/96yqf/esqn/uqQqxAAAAAC7oyQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtZ8WAAAAAADesqn/3rKp/96yqf/esqn/3rKp/7ukIHresqn/3rKp/96yqf/esqn/3rKp/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3rKp/96yqf/esqn/3rKp/96yqf/esqn/wK1BXN6yqf/esqn/3rKp/96yqf/esqn/uKAYUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL+oO1Hesqn/3rKp/96yqf/esqn/3rKp/76pLXq3nx023rKp/96yqf/esqn/3rKp/96yqf/esqn/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAt58l896yqf/esqn/3rKp/96yqf/esqn/3rKp/wAAAADesqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/xrRRVQAAAADYzYkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM67agAAAAAAybZYUt6yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/9+/UXAAAAAN6yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/wAAAACznRMAtJ4ZV96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADesqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/ArDZ4AAAAAAAAAAAAAAAA3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/yqdi/wAAAAAAAAAAAAAAAAAAAADHplZ93rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/6Ny8U+bauVDesqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf+5oyBkAAAAAAAAAAAAAAAAAAAAAAAAAADesqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/t6Ec1wAAAAAAAAAAAAAAAAAAAAAAAAAAs5sWAOHUlQfesqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/OxHUFxbRJAAAAAAAAAAAAAAAAAAAAAAAAAAAAsJkFAN6yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/29COIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr5YBAN6yqf+7pSf43rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/uaMf+d2xp6MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyrhUAAAAAAC7pil73rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/7miH38AAAAAxrJDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADi150b2K6T4N6yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/96yqf/esqn/3rKp/7mjI5zUxHAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOnftwAAAAAAAAAAAN6yqf/esqn/3rKp/7egG+e2nxf/uKAk/7mjIvPesqn/3rKp/7agGEAAAAAAAAAAANnOjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////wD///gAP//gAAf/wAAD/4AAAf8AAAD+AAAAfgAAAHwA/wA8f//+OP///xj///8Y////CP///xh///4IP//8CD///Bgf//gID//wGAP/wBwB/4A8AP8APgAYAH4AAAB/AAAA/wAAAf+AAAH/8AAP//"` | - favicon in base64 | | gitops.json | string | `"{\n \"graphql\": {\n \"boardCounts\": [\n {\n \"graphql\": \"_case_count\",\n \"name\": \"Case\",\n \"plural\": \"Cases\"\n },\n {\n \"graphql\": \"_experiment_count\",\n \"name\": \"Experiment\",\n \"plural\": \"Experiments\"\n },\n {\n \"graphql\": \"_aliquot_count\",\n \"name\": \"Aliquot\",\n \"plural\": \"Aliquots\"\n }\n ],\n \"chartCounts\": [\n {\n \"graphql\": \"_case_count\",\n \"name\": \"Case\"\n },\n {\n \"graphql\": \"_experiment_count\",\n \"name\": \"Experiment\"\n },\n {\n \"graphql\": \"_aliquot_count\",\n \"name\": \"Aliquot\"\n }\n ],\n \"projectDetails\": \"boardCounts\"\n },\n \"components\": {\n \"appName\": \"Generic Data Commons Portal\",\n \"index\": {\n \"introduction\": {\n \"heading\": \"Data Commons\",\n \"text\": \"The Generic Data Commons supports the management, analysis and sharing of data for the research community.\",\n \"link\": \"/submission\"\n },\n \"buttons\": [\n {\n \"name\": \"Define Data Field\",\n \"icon\": \"data-field-define\",\n \"body\": \"The Generic Data Commons define the data in a general way. Please study the dictionary before you start browsing.\",\n \"link\": \"/DD\",\n \"label\": \"Learn more\"\n },\n {\n \"name\": \"Explore Data\",\n \"icon\": \"data-explore\",\n \"body\": \"The Exploration Page gives you insights and a clear overview under selected factors.\",\n \"link\": \"/explorer\",\n \"label\": \"Explore data\"\n },\n {\n \"name\": \"Access Data\",\n \"icon\": \"data-access\",\n \"body\": \"Use our selected tool to filter out the data you need.\",\n \"link\": \"/query\",\n \"label\": \"Query data\"\n },\n {\n \"name\": \"Submit Data\",\n \"icon\": \"data-submit\",\n \"body\": \"Submit Data based on the dictionary.\",\n \"link\": \"/submission\",\n \"label\": \"Submit data\"\n }\n ]\n },\n \"navigation\": {\n \"title\": \"Generic Data Commons\",\n \"items\": [\n {\n \"icon\": \"dictionary\",\n \"link\": \"/DD\",\n \"color\": \"#a2a2a2\",\n \"name\": \"Dictionary\"\n },\n {\n \"icon\": \"exploration\",\n \"link\": \"/explorer\",\n \"color\": \"#a2a2a2\",\n \"name\": \"Exploration\"\n },\n {\n \"icon\": \"query\",\n \"link\": \"/query\",\n \"color\": \"#a2a2a2\",\n \"name\": \"Query\"\n },\n {\n \"icon\": \"workspace\",\n \"link\": \"/workspace\",\n \"color\": \"#a2a2a2\",\n \"name\": \"Workspace\"\n },\n {\n \"icon\": \"profile\",\n \"link\": \"/identity\",\n \"color\": \"#a2a2a2\",\n \"name\": \"Profile\"\n }\n ]\n },\n \"topBar\": {\n \"items\": [\n {\n \"icon\": \"upload\",\n \"link\": \"/submission\",\n \"name\": \"Submit Data\"\n },\n {\n \"link\": \"https://gen3.org/resources/user\",\n \"name\": \"Documentation\"\n }\n ]\n },\n \"login\": {\n \"title\": \"Generic Data Commons\",\n \"subTitle\": \"Explore, Analyze, and Share Data\",\n \"text\": \"This website supports the management, analysis and sharing of human disease data for the research community and aims to advance basic understanding of the genetic basis of complex traits and accelerate discovery and development of therapies, diagnostic tests, and other technologies for diseases like cancer.\",\n \"contact\": \"If you have any questions about access or the registration process, please contact \",\n \"email\": \"support@datacommons.io\"\n },\n \"certs\": {},\n \"footerLogos\": [\n {\n \"src\": \"/src/img/gen3.png\",\n \"href\": \"https://ctds.uchicago.edu/gen3\",\n \"alt\": \"Gen3 Data Commons\"\n },\n {\n \"src\": \"/src/img/createdby.png\",\n \"href\": \"https://ctds.uchicago.edu/\",\n \"alt\": \"Center for Translational Data Science at the University of Chicago\"\n }\n ]\n },\n \"requiredCerts\": [],\n \"featureFlags\": {\n \"explorer\": true,\n \"noIndex\": true,\n \"analysis\": false,\n \"discovery\": false,\n \"discoveryUseAggMDS\": false,\n \"studyRegistration\": false\n },\n \"dataExplorerConfig\": {\n \"charts\": {\n \"project_id\": {\n \"chartType\": \"count\",\n \"title\": \"Projects\"\n },\n \"case_id\": {\n \"chartType\": \"count\",\n \"title\": \"Cases\"\n },\n \"gender\": {\n \"chartType\": \"pie\",\n \"title\": \"Gender\"\n },\n \"race\": {\n \"chartType\": \"bar\",\n \"title\": \"Race\"\n }\n },\n \"filters\": {\n \"tabs\": [\n {\n \"title\": \"Case\",\n \"fields\":[\n \"project_id\",\n \"gender\",\n \"race\",\n \"ethnicity\"\n ]\n }\n ]\n },\n \"table\": {\n \"enabled\": false\n },\n \"dropdowns\": {},\n \"buttons\": [],\n \"guppyConfig\": {\n \"dataType\": \"case\",\n \"nodeCountTitle\": \"Cases\",\n \"fieldMapping\": [\n { \"field\": \"disease_type\", \"name\": \"Disease type\" },\n { \"field\": \"primary_site\", \"name\": \"Site where samples were collected\"}\n ],\n \"manifestMapping\": {\n \"resourceIndexType\": \"file\",\n \"resourceIdField\": \"object_id\",\n \"referenceIdFieldInResourceIndex\": \"case_id\",\n \"referenceIdFieldInDataIndex\": \"node_id\"\n },\n \"accessibleFieldCheckList\": [\"case_id\"],\n \"accessibleValidationField\": \"case_id\"\n }\n },\n \"fileExplorerConfig\": {\n \"charts\": {\n \"data_type\": {\n \"chartType\": \"stackedBar\",\n \"title\": \"File Type\"\n },\n \"data_format\": {\n \"chartType\": \"stackedBar\",\n \"title\": \"File Format\"\n }\n },\n \"filters\": {\n \"tabs\": [\n {\n \"title\": \"File\",\n \"fields\": [\n \"project_id\",\n \"data_type\",\n \"data_format\"\n ]\n }\n ]\n },\n \"table\": {\n \"enabled\": true,\n \"fields\": [\n \"project_id\",\n \"file_name\",\n \"file_size\",\n \"object_id\"\n ]\n },\n \"dropdowns\": {},\n \"guppyConfig\": {\n \"dataType\": \"file\",\n \"fieldMapping\": [\n { \"field\": \"object_id\", \"name\": \"GUID\" }\n ],\n \"nodeCountTitle\": \"Files\",\n \"manifestMapping\": {\n \"resourceIndexType\": \"case\",\n \"resourceIdField\": \"case_id\",\n \"referenceIdFieldInResourceIndex\": \"object_id\",\n \"referenceIdFieldInDataIndex\": \"object_id\"\n },\n \"accessibleFieldCheckList\": [\"case_id\"],\n \"accessibleValidationField\": \"case_id\",\n \"downloadAccessor\": \"object_id\"\n }\n }\n}\n"` | multiline string - gitops.json | | gitops.logo | string | `"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"` | - logo in base64 | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre","tierAccessLimit":1000}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -47,7 +46,7 @@ A Helm chart for gen3 data-portal | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | @@ -56,8 +55,8 @@ A Helm chart for gen3 data-portal | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | @@ -66,7 +65,7 @@ A Helm chart for gen3 data-portal | global.publicDataSets | bool | `true` | Whether public datasets are enabled. | | global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | ARN of the reverse proxy certificate. | | global.tierAccessLevel | string | `"libre"` | Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private`. | -| global.tierAccessLimit | int | `1000` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | +| global.tierAccessLimit | int | `"1000"` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | | image | map | `{"pullPolicy":"IfNotPresent","repository":"quay.io/cdis/data-portal","tag":"master"}` | Docker image information. | | image.pullPolicy | string | `"IfNotPresent"` | Docker pull policy. | | image.repository | string | `"quay.io/cdis/data-portal"` | Docker repository. | diff --git a/helm/portal/values.yaml b/helm/portal/values.yaml index fa1e8467..b3b57347 100644 --- a/helm/portal/values.yaml +++ b/helm/portal/values.yaml @@ -1,7 +1,8 @@ # Default values for portal. # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -13,10 +14,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -46,11 +49,11 @@ global: # -- (string) Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private`. tierAccessLevel: libre # -- (int) Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. - tierAccessLimit: 1000 + tierAccessLimit: "1000" # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. diff --git a/helm/requestor/README.md b/helm/requestor/README.md index 706c6391..81e88c92 100644 --- a/helm/requestor/README.md +++ b/helm/requestor/README.md @@ -36,9 +36,8 @@ A Helm chart for gen3 Requestor Service | datadogLogsInjection | bool | `true` | If enabled, the Datadog Agent will automatically inject Datadog-specific metadata into your application logs. | | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | -| externalSecrets | map | `{"requestorSmDbcreds":null}` | External Secrets settings. | -| externalSecrets.requestorSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | -| global | map | `{"addDbgap":false,"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"onlyDbgap":false,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","slack_send_dbgap":false,"slack_webhook":"None","syncFromDbgap":false,"tierAccessLevel":"libre","userYamlS3Path":"s3://cdis-gen3-users/helm-test/user.yaml","usersync":false}` | Global configuration options. | +| externalSecrets | map | `{"dbcreds":null}` | External Secrets settings. | +| externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | global.addDbgap | bool | `false` | Force attempting a dbgap sync if "true", falls back on user.yaml | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | @@ -47,7 +46,7 @@ A Helm chart for gen3 Requestor Service | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any requestor secrets you have deployed. | @@ -60,8 +59,8 @@ A Helm chart for gen3 Requestor Service | global.onlyDbgap | bool | `false` | Forces ONLY a dbgap sync if "true", IGNORING user.yaml | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/requestor/templates/_helpers.tpl b/helm/requestor/templates/_helpers.tpl index 3af66e0b..899b723c 100644 --- a/helm/requestor/templates/_helpers.tpl +++ b/helm/requestor/templates/_helpers.tpl @@ -77,26 +77,4 @@ Create the name of the service account to use {{- else }} {{- default .Values.secrets.password }} {{- end }} -{{- end }} - -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} - {{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} - -{{/* - Service DB Creds Secrets Manager Name -*/}} -{{- define "requestor-sm-dbcreds" -}} -{{- if .Values.externalSecrets.requestorSmDbcreds }} - {{- default .Values.externalSecrets.requestorSmDbcreds }} -{{- else }} - {{- .Values.global.environment }}- {{- .Chart.Name }}-creds -{{- end -}} -{{- end -}} +{{- end }} \ No newline at end of file diff --git a/helm/requestor/templates/db-init.yaml b/helm/requestor/templates/db-init.yaml index abbefb6e..6738ad76 100644 --- a/helm/requestor/templates/db-init.yaml +++ b/helm/requestor/templates/db-init.yaml @@ -1,5 +1,6 @@ -{{ include "common.db_setup_job" . }} ---- +{{- if not .Values.global.externalSecrets.deploy }} +{{ include "common.db-secret" . }} +{{- end }} {{ include "common.db-secret" . }} --- {{ include "common.db_setup_sa" . }} diff --git a/helm/requestor/templates/external-secret.yaml b/helm/requestor/templates/external-secret.yaml index 048097fc..70c278fe 100644 --- a/helm/requestor/templates/external-secret.yaml +++ b/helm/requestor/templates/external-secret.yaml @@ -1,19 +1 @@ -{{ if .Values.global.externalSecrets.deploy }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ $.Chart.Name }}-dbcreds -spec: - refreshInterval: 5m - secretStoreRef: - name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore - target: - name: {{ $.Chart.Name }}-dbcreds - creationPolicy: Owner - data: - - secretKey: data - remoteRef: - #name of secret in secrets manager - key: {{include "requestor-sm-dbcreds" .}} -{{- end }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/requestor/values.yaml b/helm/requestor/values.yaml index 20ade152..b172815f 100644 --- a/helm/requestor/values.yaml +++ b/helm/requestor/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -63,7 +66,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. @@ -80,7 +83,7 @@ global: # -- (map) External Secrets settings. externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" - requestorSmDbcreds: + dbcreds: # -- (map) Secret information for External Secrets. secrets: # -- (str) AWS access key ID. Overrides global key. diff --git a/helm/revproxy/README.md b/helm/revproxy/README.md index c038e4ea..ce2eb8fa 100644 --- a/helm/revproxy/README.md +++ b/helm/revproxy/README.md @@ -26,7 +26,6 @@ A Helm chart for gen3 revproxy | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre","tierAccessLimit":1000,"tls":{"cert":null,"key":null}}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -34,7 +33,7 @@ A Helm chart for gen3 revproxy | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | @@ -43,8 +42,8 @@ A Helm chart for gen3 revproxy | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | @@ -53,7 +52,9 @@ A Helm chart for gen3 revproxy | global.publicDataSets | bool | `true` | Whether public datasets are enabled. | | global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | ARN of the reverse proxy certificate. | | global.tierAccessLevel | string | `"libre"` | Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` | -| global.tierAccessLimit | int | `1000` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | +| global.tierAccessLimit | int | `"1000"` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | +| global.tls.cert | string | `nil` | | +| global.tls.key | string | `nil` | | | image | map | `{"pullPolicy":"Always","repository":"nginx","tag":"stable-perl"}` | Docker image information. | | image.pullPolicy | string | `"Always"` | Docker pull policy. | | image.repository | string | `"nginx"` | Docker repository. | diff --git a/helm/revproxy/values.yaml b/helm/revproxy/values.yaml index 9c1c9b02..80039806 100644 --- a/helm/revproxy/values.yaml +++ b/helm/revproxy/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: tls: cert: @@ -17,10 +18,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -50,11 +53,11 @@ global: # -- (string) Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` tierAccessLevel: libre # -- (int) Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. - tierAccessLimit: 1000 + tierAccessLimit: "1000" # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. diff --git a/helm/sheepdog/README.md b/helm/sheepdog/README.md index 7f707caf..1e095b5b 100644 --- a/helm/sheepdog/README.md +++ b/helm/sheepdog/README.md @@ -37,10 +37,9 @@ A Helm chart for gen3 Sheepdog Service | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| externalSecrets | map | `{"sheepdogSmDbcreds":null}` | External Secrets settings. | -| externalSecrets.sheepdogSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | +| externalSecrets | map | `{"dbcreds":null}` | External Secrets settings. | +| externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fenceUrl | string | `"http://fence-service"` | URL for the fence service | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -48,7 +47,7 @@ A Helm chart for gen3 Sheepdog Service | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any sheepdog secrets you have deployed. | @@ -60,8 +59,8 @@ A Helm chart for gen3 Sheepdog Service | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/sheepdog/templates/_helpers.tpl b/helm/sheepdog/templates/_helpers.tpl index 669071f7..1c935c37 100644 --- a/helm/sheepdog/templates/_helpers.tpl +++ b/helm/sheepdog/templates/_helpers.tpl @@ -100,26 +100,4 @@ Define dictionaryUrl {{- else}} {{- .Values.dictionaryUrl }} {{- end }} -{{- end }} - -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} - {{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} - -{{/* - Service DB Creds Secrets Manager Name -*/}} -{{- define "sheepdog-sm-dbcreds" -}} -{{- if .Values.externalSecrets.sheepdogSmDbcreds }} - {{- default .Values.externalSecrets.sheepdogSmDbcreds }} -{{- else }} - {{- .Values.global.environment }}- {{- .Chart.Name }}-creds -{{- end -}} -{{- end -}} +{{- end }} \ No newline at end of file diff --git a/helm/sheepdog/templates/external-secrets.yaml b/helm/sheepdog/templates/external-secrets.yaml index 25c8912f..70c278fe 100644 --- a/helm/sheepdog/templates/external-secrets.yaml +++ b/helm/sheepdog/templates/external-secrets.yaml @@ -1,19 +1 @@ -{{ if .Values.global.externalSecrets.deploy }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ $.Chart.Name }}-dbcreds -spec: - refreshInterval: 5m - secretStoreRef: - name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore - target: - name: {{ $.Chart.Name }}-dbcreds - creationPolicy: Owner - data: - - secretKey: data - remoteRef: - #name of secret in secrets manager - key: {{include "sheepdog-sm-dbcreds" .}} -{{- end }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/sheepdog/values.yaml b/helm/sheepdog/values.yaml index 1ac1db3b..d95cddeb 100644 --- a/helm/sheepdog/values.yaml +++ b/helm/sheepdog/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -49,7 +52,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. @@ -66,7 +69,7 @@ global: # -- (map) External Secrets settings. externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" - sheepdogSmDbcreds: + dbcreds: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: diff --git a/helm/sower/README.md b/helm/sower/README.md index 8ccb3ee7..55b30141 100644 --- a/helm/sower/README.md +++ b/helm/sower/README.md @@ -33,7 +33,6 @@ A Helm chart for gen3 sower | criticalService | string | `"false"` | Valid options are "true" or "false". If invalid option is set- the value will default to "false". | | fullnameOverride | string | `""` | Override the full name of the deployment. | | gen3Namespace | string | `"default"` | Namespace to deploy the job. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","netPolicy":true,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -41,15 +40,15 @@ A Helm chart for gen3 sower | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/sower/values.yaml b/helm/sower/values.yaml index bb327782..3bc59048 100644 --- a/helm/sower/values.yaml +++ b/helm/sower/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -49,7 +52,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false diff --git a/helm/ssjdispatcher/README.md b/helm/ssjdispatcher/README.md index e09ea9f2..b5e43599 100644 --- a/helm/ssjdispatcher/README.md +++ b/helm/ssjdispatcher/README.md @@ -37,7 +37,6 @@ A Helm chart for gen3 ssjdispatcher | dispatcherJobNum | string | `"10"` | Ssjdispater job number. | | fullnameOverride | string | `""` | Override the full name of the deployment. | | gen3Namespace | string | `"default"` | Namespace to deploy the job. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -45,7 +44,7 @@ A Helm chart for gen3 ssjdispatcher | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | @@ -54,8 +53,8 @@ A Helm chart for gen3 ssjdispatcher | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/ssjdispatcher/values.yaml b/helm/ssjdispatcher/values.yaml index d1b028d7..74ed990b 100644 --- a/helm/ssjdispatcher/values.yaml +++ b/helm/ssjdispatcher/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -49,7 +52,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. diff --git a/helm/wts/README.md b/helm/wts/README.md index 266f4fb4..4d067411 100644 --- a/helm/wts/README.md +++ b/helm/wts/README.md @@ -26,10 +26,9 @@ A Helm chart for gen3 workspace token service | datadogLogsInjection | bool | `true` | If enabled, the Datadog Agent will automatically inject Datadog-specific metadata into your application logs. | | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | -| externalSecrets | map | `{"wtsSmDbcreds":null}` | External Secrets settings. | -| externalSecrets.wtsSmDbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | +| externalSecrets | map | `{"dbcreds":null}` | External Secrets settings. | +| externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | -| global | map | `{"aws":{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false},"ddEnabled":false,"dev":true,"dictionaryUrl":"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json","dispatcherJobNum":10,"environment":"default","externalSecrets":{"deploy":false,"separate":false},"hostname":"localhost","kubeBucket":"kube-gen3","logsBucket":"logs-gen3","minAvialable":1,"netPolicy":true,"pdb":false,"portalApp":"gitops","postgres":{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}},"publicDataSets":true,"revproxyArn":"arn:aws:acm:us-east-1:123456:certificate","tierAccessLevel":"libre"}` | Global configuration options. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -37,7 +36,7 @@ A Helm chart for gen3 workspace token service | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Whether the deployment is for development purposes. | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | -| global.dispatcherJobNum | int | `10` | Number of dispatcher jobs. | +| global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any wts secrets you have deployed. | @@ -49,8 +48,8 @@ A Helm chart for gen3 workspace token service | global.netPolicy | bool | `true` | Whether network policies are enabled. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | global.portalApp | string | `"gitops"` | Portal application name. | -| global.postgres | map | `{"dbCreate":true,"master":{"host":null,"password":null,"port":"5432","username":"postgres"}}` | Postgres database configuration. | | global.postgres.dbCreate | bool | `true` | Whether the database should be created. | +| global.postgres.externalSecret | string | `""` | Name of external secret. Disabled if empty | | global.postgres.master | map | `{"host":null,"password":null,"port":"5432","username":"postgres"}` | Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres | | global.postgres.master.host | string | `nil` | hostname of postgres server | | global.postgres.master.password | string | `nil` | password for superuser in postgres. This is used to create or restore databases | diff --git a/helm/wts/templates/_helpers.tpl b/helm/wts/templates/_helpers.tpl index a4b820b5..a8a094c0 100644 --- a/helm/wts/templates/_helpers.tpl +++ b/helm/wts/templates/_helpers.tpl @@ -79,25 +79,3 @@ Create the name of the service account to use {{- default .Values.postgres.password }} {{- end }} {{- end }} - -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} - {{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} - -{{/* - Service DB Creds Secrets Manager Name -*/}} -{{- define "wts-sm-dbcreds" -}} -{{- if .Values.externalSecrets.wtsSmDbcreds }} - {{- default .Values.externalSecrets.wtsSmDbcreds }} -{{- else }} - {{- .Values.global.environment }}- {{- .Chart.Name }}-creds -{{- end -}} -{{- end -}} diff --git a/helm/wts/templates/db-init.yaml b/helm/wts/templates/db-init.yaml index abbefb6e..6738ad76 100644 --- a/helm/wts/templates/db-init.yaml +++ b/helm/wts/templates/db-init.yaml @@ -1,5 +1,6 @@ -{{ include "common.db_setup_job" . }} ---- +{{- if not .Values.global.externalSecrets.deploy }} +{{ include "common.db-secret" . }} +{{- end }} {{ include "common.db-secret" . }} --- {{ include "common.db_setup_sa" . }} diff --git a/helm/wts/templates/external-secret.yaml b/helm/wts/templates/external-secret.yaml index 0ac706f6..70c278fe 100644 --- a/helm/wts/templates/external-secret.yaml +++ b/helm/wts/templates/external-secret.yaml @@ -1,19 +1 @@ -{{ if .Values.global.externalSecrets.deploy }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ $.Chart.Name }}-dbcreds -spec: - refreshInterval: 5m - secretStoreRef: - name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore - target: - name: {{ $.Chart.Name }}-dbcreds - creationPolicy: Owner - data: - - secretKey: data - remoteRef: - #name of secret in secrets manager - key: {{include "wts-sm-dbcreds" .}} -{{- end }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/wts/values.yaml b/helm/wts/values.yaml index e4ec06f6..2a440cee 100644 --- a/helm/wts/values.yaml +++ b/helm/wts/values.yaml @@ -2,7 +2,8 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# -- (map) Global configuration options. + +# Global configuration global: # -- (map) AWS configuration aws: @@ -14,10 +15,12 @@ global: awsSecretAccessKey: # -- (bool) Whether the deployment is for development purposes. dev: true - # -- (map) Postgres database configuration. + postgres: # -- (bool) Whether the database should be created. dbCreate: true + # -- (string) Name of external secret. Disabled if empty + externalSecret: "" # -- (map) Master credentials to postgres. This is going to be the default postgres server being used for each service, unless each service specifies their own postgres master: # -- (string) hostname of postgres server @@ -49,7 +52,7 @@ global: # -- (bool) Whether network policies are enabled. netPolicy: true # -- (int) Number of dispatcher jobs. - dispatcherJobNum: 10 + dispatcherJobNum: "10" # -- (bool) Whether Datadog is enabled. ddEnabled: false # -- (bool) If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. @@ -66,7 +69,7 @@ global: # -- (map) External Secrets settings. externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" - wtsSmDbcreds: + dbcreds: # -- (map) Postgres database configuration. If db does not exist in postgres cluster and dbCreate is set ot true then these databases will be created for you postgres: From e8ecba5e5067362afaf876853d6e86aea55ea482 Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Thu, 7 Sep 2023 17:33:09 -0600 Subject: [PATCH 18/60] quote troublesome env var --- helm/guppy/templates/deployment.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helm/guppy/templates/deployment.yaml b/helm/guppy/templates/deployment.yaml index ebb8bcac..9496be65 100644 --- a/helm/guppy/templates/deployment.yaml +++ b/helm/guppy/templates/deployment.yaml @@ -71,9 +71,9 @@ spec: value: {{ . }} {{- end }} - name: TIER_ACCESS_LEVEL - value: {{ .Values.global.tierAccessLevel }} + value: {{ .Values.global.tierAccessLevel | quote }} - name: TIER_ACCESS_LIMIT - value: {{ .Values.global.tierAccessLimit }} + value: {{ .Values.global.tierAccessLimit | quote}} {{- with .Values.volumeMounts }} From 6f8a43cfbf3336f57e228f193d30b7b1d10d429b Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Thu, 7 Sep 2023 18:04:32 -0600 Subject: [PATCH 19/60] Fix db-init --- helm/arborist/templates/db-init.yaml | 5 +++-- helm/audit/templates/db-init.yaml | 3 ++- helm/fence/templates/db-init.yaml | 5 +++-- helm/peregrine/templates/db-init.yaml | 5 +++-- helm/requestor/templates/db-init.yaml | 5 +++-- helm/wts/templates/db-init.yaml | 3 ++- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/helm/arborist/templates/db-init.yaml b/helm/arborist/templates/db-init.yaml index 6738ad76..56e1ea41 100644 --- a/helm/arborist/templates/db-init.yaml +++ b/helm/arborist/templates/db-init.yaml @@ -1,7 +1,8 @@ {{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} {{- end }} -{{ include "common.db-secret" . }} --- -{{ include "common.db_setup_sa" . }} +{{ include "common.db_setup_job" . }} --- +{{ include "common.db_setup_sa" . }} +--- \ No newline at end of file diff --git a/helm/audit/templates/db-init.yaml b/helm/audit/templates/db-init.yaml index f691b8e9..56e1ea41 100644 --- a/helm/audit/templates/db-init.yaml +++ b/helm/audit/templates/db-init.yaml @@ -1,7 +1,8 @@ {{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} {{- end }} -{{ include "common.db-secret" . }} +--- +{{ include "common.db_setup_job" . }} --- {{ include "common.db_setup_sa" . }} --- \ No newline at end of file diff --git a/helm/fence/templates/db-init.yaml b/helm/fence/templates/db-init.yaml index 6738ad76..56e1ea41 100644 --- a/helm/fence/templates/db-init.yaml +++ b/helm/fence/templates/db-init.yaml @@ -1,7 +1,8 @@ {{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} {{- end }} -{{ include "common.db-secret" . }} --- -{{ include "common.db_setup_sa" . }} +{{ include "common.db_setup_job" . }} --- +{{ include "common.db_setup_sa" . }} +--- \ No newline at end of file diff --git a/helm/peregrine/templates/db-init.yaml b/helm/peregrine/templates/db-init.yaml index 6738ad76..56e1ea41 100644 --- a/helm/peregrine/templates/db-init.yaml +++ b/helm/peregrine/templates/db-init.yaml @@ -1,7 +1,8 @@ {{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} {{- end }} -{{ include "common.db-secret" . }} --- -{{ include "common.db_setup_sa" . }} +{{ include "common.db_setup_job" . }} --- +{{ include "common.db_setup_sa" . }} +--- \ No newline at end of file diff --git a/helm/requestor/templates/db-init.yaml b/helm/requestor/templates/db-init.yaml index 6738ad76..56e1ea41 100644 --- a/helm/requestor/templates/db-init.yaml +++ b/helm/requestor/templates/db-init.yaml @@ -1,7 +1,8 @@ {{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} {{- end }} -{{ include "common.db-secret" . }} --- -{{ include "common.db_setup_sa" . }} +{{ include "common.db_setup_job" . }} --- +{{ include "common.db_setup_sa" . }} +--- \ No newline at end of file diff --git a/helm/wts/templates/db-init.yaml b/helm/wts/templates/db-init.yaml index 6738ad76..1e55878d 100644 --- a/helm/wts/templates/db-init.yaml +++ b/helm/wts/templates/db-init.yaml @@ -1,7 +1,8 @@ {{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} {{- end }} -{{ include "common.db-secret" . }} +--- +{{ include "common.db_setup_job" . }} --- {{ include "common.db_setup_sa" . }} --- From 8f2632c8b2d3f7d7e5d6f281be4a507d5406f805 Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Thu, 7 Sep 2023 18:06:43 -0600 Subject: [PATCH 20/60] Conditional dbCreate --- helm/common/templates/_db_setup_job.tpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/helm/common/templates/_db_setup_job.tpl b/helm/common/templates/_db_setup_job.tpl index f48decb9..d1f49c1f 100644 --- a/helm/common/templates/_db_setup_job.tpl +++ b/helm/common/templates/_db_setup_job.tpl @@ -31,6 +31,7 @@ roleRef: # DB Setup Job {{- define "common.db_setup_job" -}} +{{- if or $.Values.global.postgres.dbCreate $.Values.postgres.dbCreate }} apiVersion: batch/v1 kind: Job metadata: @@ -160,6 +161,7 @@ spec: # Update secret to signal that db has been created, and services can start kubectl patch secret/{{ .Chart.Name }}-dbcreds -p '{"data":{"dbcreated":"dHJ1ZQo="}}' fi +{{- end}} {{- end }} From 6f0c0b27ede140d74ef50e09808c75c1f9d28f94 Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Mon, 11 Sep 2023 12:38:00 -0600 Subject: [PATCH 21/60] set TLS 1.3 in aws --- helm/revproxy/templates/ingress_aws.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/helm/revproxy/templates/ingress_aws.yaml b/helm/revproxy/templates/ingress_aws.yaml index 7b0760c3..530e276b 100644 --- a/helm/revproxy/templates/ingress_aws.yaml +++ b/helm/revproxy/templates/ingress_aws.yaml @@ -10,6 +10,7 @@ metadata: alb.ingress.kubernetes.io/group.name: {{ .Values.global.environment }} alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' + alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06 spec: ingressClassName: alb rules: From 32feb909496043ef243023aae5896dbf7f4d0cf7 Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Mon, 11 Sep 2023 14:47:13 -0600 Subject: [PATCH 22/60] Add indexd-service creds to externalSecrets --- helm/indexd/README.md | 2 +- helm/indexd/templates/external-secrets.yaml | 22 ++++++++++++++++++++- helm/indexd/values.yaml | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/helm/indexd/README.md b/helm/indexd/README.md index e7698753..e387d035 100644 --- a/helm/indexd/README.md +++ b/helm/indexd/README.md @@ -27,7 +27,7 @@ A Helm chart for gen3 indexd | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | defaultPrefix | string | `"PREFIX/"` | default prefix for indexd | | env | list | `[{"name":"ARBORIST","value":"true"},{"name":"GEN3_DEBUG","value":"False"}]` | Environment variables to pass to the container | -| externalSecrets | map | `{"dbcreds":null}` | External Secrets settings. | +| externalSecrets | map | `{"dbcreds":null,"serviceCreds":"indexd-service-creds"}` | External Secrets settings. | | externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | diff --git a/helm/indexd/templates/external-secrets.yaml b/helm/indexd/templates/external-secrets.yaml index 70c278fe..f80a4920 100644 --- a/helm/indexd/templates/external-secrets.yaml +++ b/helm/indexd/templates/external-secrets.yaml @@ -1 +1,21 @@ -{{ include "common.externalSecret.db" . }} \ No newline at end of file +{{ include "common.externalSecret.db" . }} +--- +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: indexd-service-creds +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: indexd-service-creds + creationPolicy: Owner + dataFrom: + - extract: + key: {{ .Values.externalSecrets.serviceCreds }} + conversionStrategy: Default + decodingStrategy: None +{{- end }} \ No newline at end of file diff --git a/helm/indexd/values.yaml b/helm/indexd/values.yaml index ec9379bb..39f424fc 100644 --- a/helm/indexd/values.yaml +++ b/helm/indexd/values.yaml @@ -72,6 +72,7 @@ global: externalSecrets: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" dbcreds: + serviceCreds: "indexd-service-creds" # -- (map) Values for indexd secret. secrets: From 8bf1983062133ca13d1f7b4d6c711b475a85de29 Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Mon, 11 Sep 2023 15:15:18 -0600 Subject: [PATCH 23/60] Add aws-es-proxy creds to secrets manager --- helm/aws-es-proxy/README.md | 2 ++ .../templates/external-secrets.yaml | 19 +++++++++++++++++++ helm/aws-es-proxy/values.yaml | 5 +++++ 3 files changed, 26 insertions(+) create mode 100644 helm/aws-es-proxy/templates/external-secrets.yaml diff --git a/helm/aws-es-proxy/README.md b/helm/aws-es-proxy/README.md index 3c0e30b7..ab1f091d 100644 --- a/helm/aws-es-proxy/README.md +++ b/helm/aws-es-proxy/README.md @@ -26,6 +26,8 @@ A Helm chart for AWS ES Proxy Service for gen3 | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | esEndpoint | str | `"test.us-east-1.es.amazonaws.com"` | Elasticsearch endpoint in AWS | +| externalSecrets | map | `{"awsCreds":"aws-es-proxy-aws-credentials"}` | External Secrets settings. | +| externalSecrets.awsCreds | string | `"aws-es-proxy-aws-credentials"` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | diff --git a/helm/aws-es-proxy/templates/external-secrets.yaml b/helm/aws-es-proxy/templates/external-secrets.yaml new file mode 100644 index 00000000..5f963657 --- /dev/null +++ b/helm/aws-es-proxy/templates/external-secrets.yaml @@ -0,0 +1,19 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-es-proxy-aws-config +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "cluster-secret-store" .}} + kind: ClusterSecretStore + target: + name: aws-es-proxy-aws-config + creationPolicy: Owner + data: + - secretKey: credentials + remoteRef: + #name of secret in secrets manager + key: {{ .Values.externalSecrets.awsCreds }} +{{- end }} \ No newline at end of file diff --git a/helm/aws-es-proxy/values.yaml b/helm/aws-es-proxy/values.yaml index 1666f771..ee4989ab 100644 --- a/helm/aws-es-proxy/values.yaml +++ b/helm/aws-es-proxy/values.yaml @@ -22,6 +22,11 @@ global: # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 +# -- (map) External Secrets settings. +externalSecrets: + # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" + awsCreds: "aws-es-proxy-aws-credentials" + # -- (map) Annotations to add to the pod podAnnotations: From 33f033e25f8336902773dc7eb5bf5f7cc889c8a3 Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Mon, 11 Sep 2023 16:44:52 -0600 Subject: [PATCH 24/60] do not create secrets, if external secrets is enabled --- helm/fence/templates/fence-config.yaml | 4 +++- helm/indexd/templates/indexd-secret.yaml | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/helm/fence/templates/fence-config.yaml b/helm/fence/templates/fence-config.yaml index 29d0df2e..e50568ee 100644 --- a/helm/fence/templates/fence-config.yaml +++ b/helm/fence/templates/fence-config.yaml @@ -1,3 +1,4 @@ +{{ if not .Values.global.externalSecrets.deploy }} apiVersion: v1 kind: Secret metadata: @@ -8,4 +9,5 @@ stringData: {{- with .Values.FENCE_CONFIG }} {{- toYaml . | nindent 4 }} {{ end }} ---- \ No newline at end of file +--- +{{- end }} \ No newline at end of file diff --git a/helm/indexd/templates/indexd-secret.yaml b/helm/indexd/templates/indexd-secret.yaml index 7c7ca648..65c79f19 100644 --- a/helm/indexd/templates/indexd-secret.yaml +++ b/helm/indexd/templates/indexd-secret.yaml @@ -6,6 +6,7 @@ type: Opaque data: {{ (.Files.Glob "indexd-settings/*").AsSecrets | indent 2 }} --- +{{ if .Values.global.externalSecrets.deploy }} apiVersion: v1 kind: Secret metadata: @@ -14,3 +15,4 @@ type: Opaque data: fence: {{ include "common.getOrGenSecret" (list .Values.secrets.userdb.fence "indexd-service-creds" "fence" 20 .Release.Namespace) }} sheepdog: {{ include "common.getOrGenSecret" (list .Values.secrets.userdb.sheepdog "indexd-service-creds" "sheepdog" 20 .Release.Namespace) }} +{{- end }} \ No newline at end of file From 590eec021951e512d4cd91ace77ce68565f5530e Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Mon, 11 Sep 2023 16:48:08 -0600 Subject: [PATCH 25/60] do not create secrets, if external secrets is enabled --- helm/indexd/templates/indexd-secret.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/indexd/templates/indexd-secret.yaml b/helm/indexd/templates/indexd-secret.yaml index 65c79f19..a970e9a1 100644 --- a/helm/indexd/templates/indexd-secret.yaml +++ b/helm/indexd/templates/indexd-secret.yaml @@ -6,7 +6,7 @@ type: Opaque data: {{ (.Files.Glob "indexd-settings/*").AsSecrets | indent 2 }} --- -{{ if .Values.global.externalSecrets.deploy }} +{{ if not .Values.global.externalSecrets.deploy }} apiVersion: v1 kind: Secret metadata: From 558bbce657ee6e04012b35e169cda34682fbd2ce Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Mon, 25 Sep 2023 16:03:55 -0500 Subject: [PATCH 26/60] Moving reference to externalSecrets to common chart --- helm/audit/templates/_helpers.tpl | 10 ---- helm/audit/templates/external-secret.yaml | 2 +- .../templates/external-secrets.yaml | 2 +- .../templates/_cluster_secret_store.tpl | 24 --------- helm/common/templates/_external_secrets.tpl | 49 ++++++++++++++++++- helm/fence/templates/_helpers.tpl | 21 -------- helm/fence/templates/external-secret.yaml | 8 +-- helm/indexd/templates/_helpers.tpl | 11 ----- helm/indexd/templates/external-secrets.yaml | 2 +- helm/manifestservice/templates/_helpers.tpl | 11 ----- .../templates/external-secret.yaml | 2 +- helm/peregrine/templates/_helpers.tpl | 22 --------- 12 files changed, 56 insertions(+), 108 deletions(-) delete mode 100644 helm/common/templates/_cluster_secret_store.tpl diff --git a/helm/audit/templates/_helpers.tpl b/helm/audit/templates/_helpers.tpl index ee0e4c3f..6f70cc66 100644 --- a/helm/audit/templates/_helpers.tpl +++ b/helm/audit/templates/_helpers.tpl @@ -79,16 +79,6 @@ Create the name of the service account to use {{- end }} {{- end }} -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} - {{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} {{/* Audit g3 Auto Secrets Manager Name diff --git a/helm/audit/templates/external-secret.yaml b/helm/audit/templates/external-secret.yaml index 6302b3d2..f8b3df61 100644 --- a/helm/audit/templates/external-secret.yaml +++ b/helm/audit/templates/external-secret.yaml @@ -6,7 +6,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "cluster-secret-store" .}} + name: {{include "common.clusterSecretStore" .}} kind: ClusterSecretStore target: name: audit-g3auto diff --git a/helm/aws-es-proxy/templates/external-secrets.yaml b/helm/aws-es-proxy/templates/external-secrets.yaml index 5f963657..07d2d4ba 100644 --- a/helm/aws-es-proxy/templates/external-secrets.yaml +++ b/helm/aws-es-proxy/templates/external-secrets.yaml @@ -6,7 +6,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "cluster-secret-store" .}} + name: {{include "common.clusterSecretStore" .}} kind: ClusterSecretStore target: name: aws-es-proxy-aws-config diff --git a/helm/common/templates/_cluster_secret_store.tpl b/helm/common/templates/_cluster_secret_store.tpl deleted file mode 100644 index 03261581..00000000 --- a/helm/common/templates/_cluster_secret_store.tpl +++ /dev/null @@ -1,24 +0,0 @@ -{{/* - External Secrets Secret Store will allow all charts to allow for authentication to AWS Secrets Manager -*/}} -{{ define "common.secretstore" -}} -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: {{.Chart.Name}}-secret-store -spec: - provider: - aws: - service: SecretsManager - region: us-east-1 - auth: - secretRef: - accessKeyIDSecretRef: - name: {{.Chart.Name}}-aws-config - key: access-key - namespace: default - secretAccessKeySecretRef: - name: {{.Chart.Name}}-aws-config - key: secret-access-key - namespace: default -{{- end }} \ No newline at end of file diff --git a/helm/common/templates/_external_secrets.tpl b/helm/common/templates/_external_secrets.tpl index fd8f402e..10a77cb8 100644 --- a/helm/common/templates/_external_secrets.tpl +++ b/helm/common/templates/_external_secrets.tpl @@ -10,6 +10,8 @@ {{- end -}} + + {{/* ExternalSecrets Object */}} @@ -22,7 +24,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "cluster-secret-store" .}} + name: {{include "common.clusterSecretStore" .}} kind: ClusterSecretStore target: name: {{ $.Chart.Name }}-dbcreds @@ -34,3 +36,48 @@ spec: decodingStrategy: None {{- end }} {{- end -}} + + +{{/* + External Secrets Secret Store will allow all charts to allow for authentication to AWS Secrets Manager +*/}} +{{ define "common.secretstore" -}} +apiVersion: external-secrets.io/v1beta1 +kind: ClusterSecretStore +metadata: + name: {{.Chart.Name}}-secret-store +spec: + provider: + aws: + service: SecretsManager + region: us-east-1 + auth: + secretRef: + accessKeyIDSecretRef: + name: {{.Chart.Name}}-aws-config + key: access-key + namespace: default + secretAccessKeySecretRef: + name: {{.Chart.Name}}-aws-config + key: secret-access-key + namespace: default +{{- end }} + + + +{{/* + # Name of the clusterSecretStore + # We want to allow override here, in case a chart is being deployed without the umbrella chart, + # or any other needs to deploy a separate secret store per service. +*/}} + +{{/* + Cluster Secret Store for External Secrets +*/}} +{{- define "common.clusterSecretStore" -}} +{{- if .Values.global.externalSecrets.separate }} + {{- .Chart.Name }}-secret-store +{{- else }} +{{- default "gen3-secret-store"}} +{{- end -}} +{{- end -}} diff --git a/helm/fence/templates/_helpers.tpl b/helm/fence/templates/_helpers.tpl index 28372690..c4a4aa77 100644 --- a/helm/fence/templates/_helpers.tpl +++ b/helm/fence/templates/_helpers.tpl @@ -97,16 +97,6 @@ Create the name of the service account to use {{- end }} {{- end }} -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} -{{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} {{/* Fence JWT Keys Secrets Manager Name @@ -135,14 +125,3 @@ Create the name of the service account to use {{- define "fence-config" -}} {{- default "fence-config" .Values.externalSecrets.fenceConfig }} {{- end }} - -{{/* - Service DB Creds Secrets Manager Name -*/}} -{{- define "fence-sm-dbcreds" -}} -{{- if .Values.externalSecrets.fenceSmDbcreds }} - {{- default .Values.externalSecrets.fenceSmDbcreds }} -{{- else }} - {{- .Values.global.environment }}- {{- .Chart.Name }}-creds -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/helm/fence/templates/external-secret.yaml b/helm/fence/templates/external-secret.yaml index b5115387..1262f9d0 100644 --- a/helm/fence/templates/external-secret.yaml +++ b/helm/fence/templates/external-secret.yaml @@ -6,7 +6,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "cluster-secret-store" .}} + name: {{include "common.clusterSecretStore" .}} kind: ClusterSecretStore target: name: fence-jwt-keys @@ -24,7 +24,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "cluster-secret-store" .}} + name: {{include "common.clusterSecretStore .}} kind: ClusterSecretStore target: name: fence-google-app-creds-secret @@ -42,7 +42,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "cluster-secret-store" .}} + name: {{include "common.clusterSecretStore" .}} kind: ClusterSecretStore target: name: fence-google-storage-creds-secret @@ -60,7 +60,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "cluster-secret-store" .}} + name: {{include "common.clusterSecretStore" .}} kind: ClusterSecretStore target: name: fence-config diff --git a/helm/indexd/templates/_helpers.tpl b/helm/indexd/templates/_helpers.tpl index 0c6704b6..5778d510 100644 --- a/helm/indexd/templates/_helpers.tpl +++ b/helm/indexd/templates/_helpers.tpl @@ -102,14 +102,3 @@ Create the name of the service account to use {{- define "indexd-gateway-creds" -}} {{- default (randAlphaNum 32) .Values.secrets.userdb.gateway }} {{- end }} - -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} - {{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} diff --git a/helm/indexd/templates/external-secrets.yaml b/helm/indexd/templates/external-secrets.yaml index f80a4920..95485e5b 100644 --- a/helm/indexd/templates/external-secrets.yaml +++ b/helm/indexd/templates/external-secrets.yaml @@ -8,7 +8,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "cluster-secret-store" .}} + name: {{include "common.clusterSecretStore" .}} kind: ClusterSecretStore target: name: indexd-service-creds diff --git a/helm/manifestservice/templates/_helpers.tpl b/helm/manifestservice/templates/_helpers.tpl index b9702720..fb9b68c7 100644 --- a/helm/manifestservice/templates/_helpers.tpl +++ b/helm/manifestservice/templates/_helpers.tpl @@ -66,17 +66,6 @@ Create the name of the service account to use {{- end }} {{- end }} -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} -{{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} - {{/* Audit g3 Auto Secrets Manager Name */}} diff --git a/helm/manifestservice/templates/external-secret.yaml b/helm/manifestservice/templates/external-secret.yaml index 27b2c143..af54469f 100644 --- a/helm/manifestservice/templates/external-secret.yaml +++ b/helm/manifestservice/templates/external-secret.yaml @@ -6,7 +6,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "cluster-secret-store" .}} + name: {{include "common.clusterSecretStore" .}} kind: ClusterSecretStore target: name: manifestservice-g3auto diff --git a/helm/peregrine/templates/_helpers.tpl b/helm/peregrine/templates/_helpers.tpl index 68bb8634..4d1439e0 100644 --- a/helm/peregrine/templates/_helpers.tpl +++ b/helm/peregrine/templates/_helpers.tpl @@ -91,25 +91,3 @@ Define dictionaryUrl {{- .Values.dictionaryUrl }} {{- end }} {{- end }} - -{{/* - Cluster Secret Store for External Secrets -*/}} -{{- define "cluster-secret-store" -}} -{{- if .Values.global.externalSecrets.separate }} - {{- .Chart.Name }}-secret-store -{{- else }} - {{- default "gen3-secret-store"}} -{{- end -}} -{{- end -}} - -{{/* - Service DB Creds Secrets Manager Name -*/}} -{{- define "peregrine-sm-dbcreds" -}} -{{- if .Values.externalSecrets.peregrineSmDbcreds }} - {{- default .Values.externalSecrets.peregrineSmDbcreds }} -{{- else }} - {{- .Values.global.environment }}- {{- .Chart.Name }}-creds -{{- end -}} -{{- end -}} From ff4d840773e4952cd99850b8433c98f86d5140a3 Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Mon, 25 Sep 2023 16:23:16 -0500 Subject: [PATCH 27/60] Moving reference to externalSecrets to common chart --- helm/fence/templates/external-secret.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/fence/templates/external-secret.yaml b/helm/fence/templates/external-secret.yaml index 1262f9d0..6a6e661f 100644 --- a/helm/fence/templates/external-secret.yaml +++ b/helm/fence/templates/external-secret.yaml @@ -24,7 +24,7 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore .}} + name: {{include "common.clusterSecretStore" .}} kind: ClusterSecretStore target: name: fence-google-app-creds-secret From ab7ce28e87fb8dedd2ad58aeb148ed297b11fa1d Mon Sep 17 00:00:00 2001 From: Jawad Qureshi Date: Mon, 25 Sep 2023 16:38:07 -0500 Subject: [PATCH 28/60] Add global values to aws-es-proxy chart --- helm/aws-es-proxy/README.md | 2 ++ helm/aws-es-proxy/values.yaml | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/helm/aws-es-proxy/README.md b/helm/aws-es-proxy/README.md index ab1f091d..3d0b7d6f 100644 --- a/helm/aws-es-proxy/README.md +++ b/helm/aws-es-proxy/README.md @@ -34,6 +34,8 @@ A Helm chart for AWS ES Proxy Service for gen3 | global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | +| global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any audit secrets you have deployed. | +| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | | global.minAvialable | int | `1` | The minimum amount of pods that are available at all times if the PDB is deployed. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | image | map | `{"pullPolicy":"Always","repository":"quay.io/cdis/aws-es-proxy","tag":""}` | Docker image information. | diff --git a/helm/aws-es-proxy/values.yaml b/helm/aws-es-proxy/values.yaml index ee4989ab..6f896e48 100644 --- a/helm/aws-es-proxy/values.yaml +++ b/helm/aws-es-proxy/values.yaml @@ -21,6 +21,11 @@ global: pdb: false # -- (int) The minimum amount of pods that are available at all times if the PDB is deployed. minAvialable: 1 + externalSecrets: + # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any audit secrets you have deployed. + deploy: false + # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. + separate: false # -- (map) External Secrets settings. externalSecrets: From d51b8fdbbed970e0ab1acd98b1406e342d1390a6 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Fri, 19 Jan 2024 15:20:30 -0700 Subject: [PATCH 29/60] fixing dependency chart versions --- helm/ambassador/Chart.yaml | 2 +- helm/ambassador/README.md | 2 +- helm/arborist/Chart.yaml | 2 +- helm/arborist/README.md | 2 +- helm/argo-wrapper/Chart.yaml | 2 +- helm/argo-wrapper/README.md | 2 +- helm/audit/Chart.yaml | 2 +- helm/audit/README.md | 2 +- helm/aws-es-proxy/Chart.yaml | 2 +- helm/aws-es-proxy/README.md | 2 +- helm/dicom-server/Chart.yaml | 2 +- helm/dicom-server/README.md | 2 +- helm/dicom-viewer/Chart.yaml | 2 +- helm/dicom-viewer/README.md | 2 +- helm/fence/Chart.yaml | 2 +- helm/fence/README.md | 2 +- helm/gen3/Chart.yaml | 42 ++++++++++++++++----------------- helm/gen3/README.md | 42 ++++++++++++++++----------------- helm/guppy/Chart.yaml | 2 +- helm/guppy/README.md | 2 +- helm/hatchery/Chart.yaml | 2 +- helm/hatchery/README.md | 2 +- helm/indexd/Chart.yaml | 2 +- helm/indexd/README.md | 2 +- helm/manifestservice/Chart.yaml | 2 +- helm/manifestservice/README.md | 2 +- helm/metadata/Chart.yaml | 2 +- helm/metadata/README.md | 2 +- helm/peregrine/Chart.yaml | 2 +- helm/peregrine/README.md | 2 +- helm/pidgin/Chart.yaml | 2 +- helm/pidgin/README.md | 2 +- helm/portal/Chart.yaml | 2 +- helm/portal/README.md | 2 +- helm/requestor/Chart.yaml | 2 +- helm/requestor/README.md | 2 +- helm/revproxy/Chart.yaml | 2 +- helm/revproxy/README.md | 2 +- helm/sheepdog/Chart.yaml | 2 +- helm/sheepdog/README.md | 2 +- helm/sower/Chart.yaml | 2 +- helm/sower/README.md | 2 +- helm/ssjdispatcher/Chart.yaml | 2 +- helm/ssjdispatcher/README.md | 2 +- helm/wts/Chart.yaml | 2 +- helm/wts/README.md | 2 +- 46 files changed, 86 insertions(+), 86 deletions(-) diff --git a/helm/ambassador/Chart.yaml b/helm/ambassador/Chart.yaml index f308da7c..a1f18334 100644 --- a/helm/ambassador/Chart.yaml +++ b/helm/ambassador/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "1.4.2" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/ambassador/README.md b/helm/ambassador/README.md index a89c854d..22427743 100644 --- a/helm/ambassador/README.md +++ b/helm/ambassador/README.md @@ -8,7 +8,7 @@ A Helm chart for deploying ambassador for gen3 | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/arborist/Chart.yaml b/helm/arborist/Chart.yaml index d3ad7ea9..d845739c 100644 --- a/helm/arborist/Chart.yaml +++ b/helm/arborist/Chart.yaml @@ -25,7 +25,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/arborist/README.md b/helm/arborist/README.md index 9dd4f29e..8e8290e9 100644 --- a/helm/arborist/README.md +++ b/helm/arborist/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 arborist | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/argo-wrapper/Chart.yaml b/helm/argo-wrapper/Chart.yaml index 02aa3e5f..de360706 100644 --- a/helm/argo-wrapper/Chart.yaml +++ b/helm/argo-wrapper/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/argo-wrapper/README.md b/helm/argo-wrapper/README.md index 6602a663..6fc88cd8 100644 --- a/helm/argo-wrapper/README.md +++ b/helm/argo-wrapper/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Argo Wrapper Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/audit/Chart.yaml b/helm/audit/Chart.yaml index 7ce95ca9..efbd8361 100644 --- a/helm/audit/Chart.yaml +++ b/helm/audit/Chart.yaml @@ -24,7 +24,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/audit/README.md b/helm/audit/README.md index 05c698d2..146545ba 100644 --- a/helm/audit/README.md +++ b/helm/audit/README.md @@ -8,7 +8,7 @@ A Helm chart for Kubernetes | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/aws-es-proxy/Chart.yaml b/helm/aws-es-proxy/Chart.yaml index b4dbc5cc..7a28cc19 100644 --- a/helm/aws-es-proxy/Chart.yaml +++ b/helm/aws-es-proxy/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/aws-es-proxy/README.md b/helm/aws-es-proxy/README.md index 5c73d993..00c6915f 100644 --- a/helm/aws-es-proxy/README.md +++ b/helm/aws-es-proxy/README.md @@ -8,7 +8,7 @@ A Helm chart for AWS ES Proxy Service for gen3 | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/dicom-server/Chart.yaml b/helm/dicom-server/Chart.yaml index ed95a1ae..44f89e8e 100644 --- a/helm/dicom-server/Chart.yaml +++ b/helm/dicom-server/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/dicom-server/README.md b/helm/dicom-server/README.md index a693ecae..b1fd0611 100644 --- a/helm/dicom-server/README.md +++ b/helm/dicom-server/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Dicom Server | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/dicom-viewer/Chart.yaml b/helm/dicom-viewer/Chart.yaml index 38969626..b31017d6 100644 --- a/helm/dicom-viewer/Chart.yaml +++ b/helm/dicom-viewer/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/dicom-viewer/README.md b/helm/dicom-viewer/README.md index 6a49d0b7..28f7f590 100644 --- a/helm/dicom-viewer/README.md +++ b/helm/dicom-viewer/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Dicom Viewer | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/fence/Chart.yaml b/helm/fence/Chart.yaml index a0d42d8a..ed6d1d7e 100644 --- a/helm/fence/Chart.yaml +++ b/helm/fence/Chart.yaml @@ -24,7 +24,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/fence/README.md b/helm/fence/README.md index 513b92ab..7fca9d38 100644 --- a/helm/fence/README.md +++ b/helm/fence/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Fence | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/gen3/Chart.yaml b/helm/gen3/Chart.yaml index 9cb89637..864b445e 100644 --- a/helm/gen3/Chart.yaml +++ b/helm/gen3/Chart.yaml @@ -5,90 +5,90 @@ description: Helm chart to deploy Gen3 Data Commons # Dependancies dependencies: - name: ambassador - version: 0.1.9 + version: 0.1.10 repository: "file://../ambassador" condition: ambassador.enabled - name: arborist - version: 0.1.9 + version: 0.1.10 repository: "file://../arborist" condition: arborist.enabled - name: argo-wrapper - version: 0.1.5 + version: 0.1.6 repository: "file://../argo-wrapper" condition: argo-wrapper.enabled - name: audit - version: 0.1.10 + version: 0.1.11 repository: "file://../audit" condition: audit.enabled - name: aws-es-proxy - version: 0.1.7 + version: 0.1.8 repository: "file://../aws-es-proxy" condition: aws-es-proxy.enabled - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: etl version: 0.1.0 repository: file://../etl condition: etl.enabled - name: fence - version: 0.1.14 + version: 0.1.15 repository: "file://../fence" condition: fence.enabled - name: guppy - version: 0.1.9 + version: 0.1.10 repository: "file://../guppy" condition: guppy.enabled - name: hatchery - version: 0.1.7 + version: 0.1.8 repository: "file://../hatchery" condition: hatchery.enabled - name: indexd - version: 0.1.11 + version: 0.1.12 repository: "file://../indexd" condition: indexd.enabled - name: manifestservice - version: 0.1.11 + version: 0.1.12 repository: "file://../manifestservice" condition: manifestservice.enabled - name: metadata - version: 0.1.9 + version: 0.1.10 repository: "file://../metadata" condition: metadata.enabled - name: peregrine - version: 0.1.10 + version: 0.1.11 repository: "file://../peregrine" condition: peregrine.enabled - name: pidgin - version: 0.1.8 + version: 0.1.9 repository: "file://../pidgin" condition: pidgin.enabled - name: portal - version: 0.1.8 + version: 0.1.9 repository: "file://../portal" condition: portal.enabled - name: requestor - version: 0.1.9 + version: 0.1.10 repository: "file://../requestor" condition: requestor.enabled - name: revproxy - version: 0.1.12 + version: 0.1.13 repository: "file://../revproxy" condition: revproxy.enabled - name: sheepdog - version: 0.1.11 + version: 0.1.12 repository: "file://../sheepdog" condition: sheepdog.enabled - name: ssjdispatcher - version: 0.1.7 + version: 0.1.8 repository: "file://../ssjdispatcher" condition: ssjdispatcher.enabled - name: sower - version: 0.1.7 + version: 0.1.8 condition: sower.enabled repository: "file://../sower" - name: wts - version: 0.1.11 + version: 0.1.12 repository: "file://../wts" condition: wts.enabled diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 4994910a..65c6aae7 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -18,28 +18,28 @@ Helm chart to deploy Gen3 Data Commons | Repository | Name | Version | |------------|------|---------| -| file://../ambassador | ambassador | 0.1.9 | -| file://../arborist | arborist | 0.1.9 | -| file://../argo-wrapper | argo-wrapper | 0.1.5 | -| file://../audit | audit | 0.1.10 | -| file://../aws-es-proxy | aws-es-proxy | 0.1.7 | -| file://../common | common | 0.1.8 | +| file://../ambassador | ambassador | 0.1.10 | +| file://../arborist | arborist | 0.1.10 | +| file://../argo-wrapper | argo-wrapper | 0.1.6 | +| file://../audit | audit | 0.1.11 | +| file://../aws-es-proxy | aws-es-proxy | 0.1.8 | +| file://../common | common | 0.1.9 | | file://../etl | etl | 0.1.0 | -| file://../fence | fence | 0.1.14 | -| file://../guppy | guppy | 0.1.9 | -| file://../hatchery | hatchery | 0.1.7 | -| file://../indexd | indexd | 0.1.11 | -| file://../manifestservice | manifestservice | 0.1.11 | -| file://../metadata | metadata | 0.1.9 | -| file://../peregrine | peregrine | 0.1.10 | -| file://../pidgin | pidgin | 0.1.8 | -| file://../portal | portal | 0.1.8 | -| file://../requestor | requestor | 0.1.9 | -| file://../revproxy | revproxy | 0.1.12 | -| file://../sheepdog | sheepdog | 0.1.11 | -| file://../sower | sower | 0.1.7 | -| file://../ssjdispatcher | ssjdispatcher | 0.1.7 | -| file://../wts | wts | 0.1.11 | +| file://../fence | fence | 0.1.15 | +| file://../guppy | guppy | 0.1.10 | +| file://../hatchery | hatchery | 0.1.8 | +| file://../indexd | indexd | 0.1.12 | +| file://../manifestservice | manifestservice | 0.1.12 | +| file://../metadata | metadata | 0.1.10 | +| file://../peregrine | peregrine | 0.1.11 | +| file://../pidgin | pidgin | 0.1.9 | +| file://../portal | portal | 0.1.9 | +| file://../requestor | requestor | 0.1.10 | +| file://../revproxy | revproxy | 0.1.13 | +| file://../sheepdog | sheepdog | 0.1.12 | +| file://../sower | sower | 0.1.8 | +| file://../ssjdispatcher | ssjdispatcher | 0.1.8 | +| file://../wts | wts | 0.1.12 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | | https://helm.elastic.co | elasticsearch | 7.10.2 | diff --git a/helm/guppy/Chart.yaml b/helm/guppy/Chart.yaml index 5cdc18d1..8da72671 100644 --- a/helm/guppy/Chart.yaml +++ b/helm/guppy/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/guppy/README.md b/helm/guppy/README.md index f7ca57e9..54611f98 100644 --- a/helm/guppy/README.md +++ b/helm/guppy/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Guppy Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/hatchery/Chart.yaml b/helm/hatchery/Chart.yaml index 74cb04a6..466cb09b 100644 --- a/helm/hatchery/Chart.yaml +++ b/helm/hatchery/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/hatchery/README.md b/helm/hatchery/README.md index 7aa4d411..583c3ac7 100644 --- a/helm/hatchery/README.md +++ b/helm/hatchery/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Hatchery | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/indexd/Chart.yaml b/helm/indexd/Chart.yaml index 2ab50739..41608207 100644 --- a/helm/indexd/Chart.yaml +++ b/helm/indexd/Chart.yaml @@ -26,7 +26,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/indexd/README.md b/helm/indexd/README.md index 96ed887b..e73bd8c6 100644 --- a/helm/indexd/README.md +++ b/helm/indexd/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 indexd | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/manifestservice/Chart.yaml b/helm/manifestservice/Chart.yaml index 5607b4b1..8557818e 100644 --- a/helm/manifestservice/Chart.yaml +++ b/helm/manifestservice/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/manifestservice/README.md b/helm/manifestservice/README.md index 3d1c8945..8141522d 100644 --- a/helm/manifestservice/README.md +++ b/helm/manifestservice/README.md @@ -8,7 +8,7 @@ A Helm chart for Kubernetes | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/metadata/Chart.yaml b/helm/metadata/Chart.yaml index d7d9cc07..0e130ab4 100644 --- a/helm/metadata/Chart.yaml +++ b/helm/metadata/Chart.yaml @@ -25,7 +25,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/metadata/README.md b/helm/metadata/README.md index 92661362..9bae11bf 100644 --- a/helm/metadata/README.md +++ b/helm/metadata/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Metadata Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | | https://helm.elastic.co | elasticsearch | 7.17.1 | diff --git a/helm/peregrine/Chart.yaml b/helm/peregrine/Chart.yaml index 53fe5bdb..eaf74f03 100644 --- a/helm/peregrine/Chart.yaml +++ b/helm/peregrine/Chart.yaml @@ -26,7 +26,7 @@ appVersion: "2023.01" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/peregrine/README.md b/helm/peregrine/README.md index 5cf156ce..57832ebe 100644 --- a/helm/peregrine/README.md +++ b/helm/peregrine/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Peregrine service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/pidgin/Chart.yaml b/helm/pidgin/Chart.yaml index 6384772b..f80d38b0 100644 --- a/helm/pidgin/Chart.yaml +++ b/helm/pidgin/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/pidgin/README.md b/helm/pidgin/README.md index 761b0843..1a34c4d7 100644 --- a/helm/pidgin/README.md +++ b/helm/pidgin/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Pidgin Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/portal/Chart.yaml b/helm/portal/Chart.yaml index cee55529..4f90c0ff 100644 --- a/helm/portal/Chart.yaml +++ b/helm/portal/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/portal/README.md b/helm/portal/README.md index 229dfbc9..542d4bc2 100644 --- a/helm/portal/README.md +++ b/helm/portal/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 data-portal | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/requestor/Chart.yaml b/helm/requestor/Chart.yaml index ab376b88..e3b94a13 100644 --- a/helm/requestor/Chart.yaml +++ b/helm/requestor/Chart.yaml @@ -26,7 +26,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/requestor/README.md b/helm/requestor/README.md index 12b69310..62a2dc5e 100644 --- a/helm/requestor/README.md +++ b/helm/requestor/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Requestor Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/revproxy/Chart.yaml b/helm/revproxy/Chart.yaml index 7bea1043..efa3c3bc 100644 --- a/helm/revproxy/Chart.yaml +++ b/helm/revproxy/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/revproxy/README.md b/helm/revproxy/README.md index 47b34539..ddb426a3 100644 --- a/helm/revproxy/README.md +++ b/helm/revproxy/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 revproxy | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/sheepdog/Chart.yaml b/helm/sheepdog/Chart.yaml index 512fd8f8..46a7945d 100644 --- a/helm/sheepdog/Chart.yaml +++ b/helm/sheepdog/Chart.yaml @@ -25,7 +25,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/sheepdog/README.md b/helm/sheepdog/README.md index 981c3904..8d0cc194 100644 --- a/helm/sheepdog/README.md +++ b/helm/sheepdog/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 Sheepdog Service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values diff --git a/helm/sower/Chart.yaml b/helm/sower/Chart.yaml index 9436fd4d..78f30033 100644 --- a/helm/sower/Chart.yaml +++ b/helm/sower/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/sower/README.md b/helm/sower/README.md index 3b736880..1217b1c3 100644 --- a/helm/sower/README.md +++ b/helm/sower/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 sower | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/ssjdispatcher/Chart.yaml b/helm/ssjdispatcher/Chart.yaml index c28556c3..34b92d4a 100644 --- a/helm/ssjdispatcher/Chart.yaml +++ b/helm/ssjdispatcher/Chart.yaml @@ -25,5 +25,5 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common diff --git a/helm/ssjdispatcher/README.md b/helm/ssjdispatcher/README.md index 44ddeee3..12c85819 100644 --- a/helm/ssjdispatcher/README.md +++ b/helm/ssjdispatcher/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 ssjdispatcher | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | ## Values diff --git a/helm/wts/Chart.yaml b/helm/wts/Chart.yaml index c63b720b..c84c4d76 100644 --- a/helm/wts/Chart.yaml +++ b/helm/wts/Chart.yaml @@ -25,7 +25,7 @@ appVersion: "master" dependencies: - name: common - version: 0.1.8 + version: 0.1.9 repository: file://../common - name: postgresql version: 11.9.13 diff --git a/helm/wts/README.md b/helm/wts/README.md index 80644d63..c951a2d2 100644 --- a/helm/wts/README.md +++ b/helm/wts/README.md @@ -8,7 +8,7 @@ A Helm chart for gen3 workspace token service | Repository | Name | Version | |------------|------|---------| -| file://../common | common | 0.1.8 | +| file://../common | common | 0.1.9 | | https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | ## Values From a31e1255df78ca479b3a7b8b12c17546cafe1659 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Fri, 19 Jan 2024 15:25:56 -0700 Subject: [PATCH 30/60] deleting extra "dbRestore" from guppy values.yaml --- .secrets.baseline | 4 ++-- helm/guppy/README.md | 1 - helm/guppy/values.yaml | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index a0accd7b..e4f23d1d 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2024-01-19T22:08:15Z", + "generated_at": "2024-01-19T22:25:52Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -339,7 +339,7 @@ "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 62, + "line_number": 61, "type": "Secret Keyword" } ], diff --git a/helm/guppy/README.md b/helm/guppy/README.md index 54611f98..f04bf9ca 100644 --- a/helm/guppy/README.md +++ b/helm/guppy/README.md @@ -37,7 +37,6 @@ A Helm chart for gen3 Guppy Service | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | dbRestore | bool | `false` | Whether or not to restore elasticsearch indices from a snapshot in s3 | -| dbRestore | bool | `false` | Whether or not to restore elasticsearch indices from a snapshot in s3 | | enableEncryptWhitelist | bool | `true` | Whether or not to enable encryption for specified fields | | encryptWhitelist | string | `"test1"` | A comma-separated list of fields to encrypt | | esEndpoint | string | `"gen3-elasticsearch-master:9200"` | Elasticsearch endpoint. | diff --git a/helm/guppy/values.yaml b/helm/guppy/values.yaml index 4ec1138c..054e4734 100644 --- a/helm/guppy/values.yaml +++ b/helm/guppy/values.yaml @@ -73,8 +73,6 @@ autoscaling: # -- (int) The target CPU utilization percentage for autoscaling targetCPUUtilizationPercentage: 80 -# -- (bool) Whether or not to restore elasticsearch indices from a snapshot in s3 -dbRestore: false # -- (map) Secret information to access the db restore job S3 bucket. secrets: # -- (str) AWS access key ID. Overrides global key. From 503155eab5fcc1cfee3156dcb2cc22d80761b82d Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:33:51 -0700 Subject: [PATCH 31/60] Update external_secrets.md --- docs/external_secrets.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index 0852135d..c8dcd5f7 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -1,6 +1,6 @@ # External Secrets Operator - "External Secrets Operator" is a tool that was created by the Kubernetes community to manage external secrets in a Kubernetes cluster. It allows you to fetch and sync external secret values from various external secret management systems into Kubernetes secrets. One of the external secret management systems it can connect to is AWS Secrets Manager. Secrets Manager allows for the secure storing of your secrets as well as the ability to periodically and automatically rotate your secrets. + "External Secrets Operator" is a tool that was created by the Kubernetes community to manage external secrets in a Kubernetes cluster. It allows you to fetch and sync external secret values from various external secret management systems into Kubernetes secrets. One of the external secret management systems it can connect to is AWS Secrets Manager. AWS Secrets Manager allows for the secure storing of your secrets as well as the ability to periodically and automatically rotate your secrets. This document will guide you through setting up the essential resources to access your secrets in AWS Secrets Manager and download the External Secrets Operator Helm chart. This way, you can effectively utilize your stored secrets with Helm. @@ -8,7 +8,7 @@ This document will guide you through setting up the essential resources to acces You can use the following Bash script to apply the External Secrets Operator to your cluster and create the necessary AWS resources. Fill in the variables below to get started: ***Notice: -The Gen3 Helm chart has various jobs and uses for an Iam user. To enhance code reusability, we've implemented the option for jobs and services to share the same AWS IAM global user. If you would like to use the same Iam user for External Secrets and jobs like ["Fence Usersync"](fence_usersync_job.md) or our "AWS ES Proxy Service", you can follow [THIS](global_iam_helm_user.md) guide that details how to setup a Helm global user. In case you opt for a global IAM user, please comment out the "create_iam_policy" and "create_iam_user" functions at the end of the script.*** +The Gen3 Helm chart has various jobs and uses for an IAM user. To enhance code reusability, we've implemented the option for jobs and services to share the same AWS IAM global user. If you would like to use the same IAM user for External Secrets and jobs like ["Fence Usersync"](fence_usersync_job.md) or our "AWS ES Proxy Service", you can follow [THIS](global_IAM_helm_user.md) guide that details how to setup a Helm global user. In case you opt for a global IAM user, please comment out the "create_iam_policy" and "create_iam_user" functions at the end of the script.*** ``` #!/bin/bash @@ -31,7 +31,7 @@ helm_install() create_iam_policy() { - echo "# ------------------ create iam policy for secrets manager --------------------------#" + echo "# ------------------ create iam policy for aws secrets manager --------------------------#" POLICY_ARN=$(aws iam create-policy --policy-name $iam_policy --policy-document '{ "Version": "2012-10-17", "Statement": [ @@ -76,17 +76,17 @@ create_iam_policy create_iam_user ``` -***Please note that Terraform for the creation and population of Gen3 Secrets in Secrets Manager is in development currently. This Terraform will also create the Iam user and policies necessary to access these secrets.*** +***Please note that Terraform for the creation and population of Gen3 Secrets in AWS Secrets Manager is in development currently. This Terraform will also create the Iam user and policies necessary to access these secrets.*** ## Enabling External Secrets in Helm charts To enable External Secrets to be used in a helm chart, you can set the `.Values.global.externalSecrets.deploy` field to "true" for an individual chart or globally by enabling this value in the Gen3 umbrella Helm chart. -If you would like to only use External Secrets for specific charts, please ensure you set `.Values.global.externalSecrets.separate` to "true" in the appropriate charts to ensure a Secret Store can be created to authenticate with Secrets Manager. +If you would like to only use External Secrets for specific charts, please ensure you set `.Values.global.externalSecrets.separate` to "true" in the appropriate charts to ensure a Secret Store can be created to authenticate with AWS Secrets Manager. -## Helm Iam User -If you are using a separate Iam user for Secrets Manager please follow the below instructions: +## Helm IAM User +If you are using a separate IAM user for AWS Secrets Manager please follow the below instructions: -This script Bash script at the beginning of this document should have created a secret titled "NameofIAMuser-user-secret" in your cluster. You will need to retrieve these values to input into your Helm chart for the Cluster Secret Store to authenticate with Secrets Manager. +This script Bash script at the beginning of this document should have created a secret titled "NameofIAMuser-user-secret" in your cluster. You will need to retrieve these values to input into your Helm chart for the Cluster Secret Store to authenticate with AWS Secrets Manager. Access Key: @@ -100,7 +100,7 @@ Secret Access Key kubectl get secret "your secret name" -o jsonpath="{.data.secret-access-key}" | base64 --decode ``` -You can paste the Iam access key and secret access key in the `.Values.secrets.awsAccessKeyId`/`.Values.secrets.awsSecretAccessKey` fields in the values.yaml file for the chart(s) you would like to use external secrets for. +You can paste the IAM access key and secret access key in the `.Values.secrets.awsAccessKeyId`/`.Values.secrets.awsSecretAccessKey` fields in the values.yaml file for the chart(s) you would like to use external secrets for. If you are deploying external secrets with the Gen3 umbrella chart, you can utilize a local secret to avoid pasting credentials in the values.yaml file. Just set `.global.aws.useLocalSecret.enabled` to true and supply your secret name. @@ -120,28 +120,28 @@ External Secrets relies on three main resources to function properly. (The below # Name of the External Secret resource name: audit-g3auto spec: - #How often to Sync with Secrets Manager + #How often to Sync with AWS Secrets Manager refreshInterval: 5m secretStoreRef: # The name of the Cluster Secret Store to use. name: {{include "cluster-secret-store" .}} kind: ClusterSecretStore target: - # What Kubernetes secret to create from the secret pulled from Secrets Manager. + # What Kubernetes secret to create from the secret pulled from AWS Secrets Manager. name: audit-g3auto creationPolicy: Owner data: # the key inside the new Kubernetes secret - secretKey: audit-service-config.yaml remoteRef: - #name of secret in secrets manager + #name of secret in AWS Secrets Manager key: {{include "audit-g3auto" .}} ``` -The External Secrets resource will usually fail with "SecretSyncedError" when it cannot find the secret name that is supplied in Secrets Manager. If this happens, the secret may still exist in Kubernetes, but it will not be overwritten by the secret value in Secrets Manager. This is helpful to know if you want to enabled the use of Secrets Manager for some, but not all the secrets in a specific Helm chart. +The External Secrets resource will usually fail with "SecretSyncedError" when it cannot find the secret name that is supplied in AWS Secrets Manager. If this happens, the secret may still exist in Kubernetes, but it will not be overwritten by the secret value in AWS Secrets Manager. This is helpful to know if you want to enabled the use of AWS Secrets Manager for some, but not all the secrets in a specific Helm chart. ## Customizing the AWS Secrets Manager Secrets Name. -When pulling a secret from secrets manager, you want to ensure that the External Secret resource is referencing the proper name of the secret in Secrets Manager. +When pulling a secret from AWS Secrets Manager, you want to ensure that the External Secret resource is referencing the proper name of the secret in AWS Secrets Manager. You can customize the name of the secret to pull from in the `.Values.externalSecrets` section of a Chart. You can see the name for the confiugrable secrets in a chart by looking in this section as well. -Any string you put in this section will override the name of the secret that is pulled from Secrets Manager NOT the name of the Kubernetes secret that is created from the External Secret resource. +Any string you put in this section will override the name of the secret that is pulled from AWS Secrets Manager NOT the name of the Kubernetes secret that is created from the External Secret resource. From d0029767917432a9ac8774211d258b0320722d56 Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 5 Feb 2024 15:36:42 -0700 Subject: [PATCH 32/60] Update PRODUCTION.md to include information about secret and configmap configuration --- docs/PRODUCTION.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/PRODUCTION.md b/docs/PRODUCTION.md index 01b85073..ed28c72b 100644 --- a/docs/PRODUCTION.md +++ b/docs/PRODUCTION.md @@ -13,3 +13,11 @@ The postgres and helm charts are included as conditionals in the Gen3 [umbrella repository: "https://charts.bitnami.com/bitnami" condition: global.dev ``` + +### Kubernetes Configmap and Secret Configuration +For the seamless operation of our services, we utilize Kubernetes secrets. To streamline the integration and management of these secrets, we highly recommend deploying External Secret Manager alongside any existing secret management systems you may already have in place. For a comprehensive guide and best practices on implementing External Secrets within our ecosystem, please consult our dedicated External Secrets Documentation available [here](https://github.com/uc-cdis/gen3-helm/blob/feat/GPE-1032/docs/external_secrets.md). + +Our services also utilize non-secret configuration variables provided via Kubernetes ConfigMaps. For streamlined management, we advise keeping your values.yaml and configuration files files in source control and utilizing ArgoCD for automatic updates and efficient management of your Gen3 Helm chart. + +Each service is designed to seamlessly integrate and manage the combination of Kubernetes secrets and ConfigMaps, ensuring the encapsulated information is effectively injected into the underlying application. + From df99089f366ce0df3322d829bead37063e82cd7d Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 5 Feb 2024 15:53:21 -0700 Subject: [PATCH 33/60] adding in cluster recommendations for Linux users --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5a63cef1..d56d16ec 100644 --- a/README.md +++ b/README.md @@ -117,8 +117,11 @@ NOTE: Gen3 helm charts are currently not used in production by CTDS, but we are For local development you must be connected to a kubernetes cluster. As referenced above in the section `Kubernetes cluster` we recommend using [Rancher Desktop](https://rancherdesktop.io/) as Kubernetes on your local machine, especially on M1 Mac's. You also get ingress and other benefits out of the box. +For MacOS users, [Minikube](https://minikube.sigs.k8s.io/docs/start/) equipped with the ingress addon serves as a viable alternative to Rancher Desktop. On Linux, we've observed that using [Kind](https://kind.sigs.k8s.io/) with an NGINX ingress installed often provides a more seamless experience compared to both Rancher Desktop and Minikube. Essentially, Helm requires access to a Kubernetes cluster with ingress capabilities, facilitating the loading of the portal in your browser for an optimal development workflow. + > **Warning** > If you are using Rancher Desktop you need to increase the vm.max_map_count as outlined [here](https://docs.rancherdesktop.io/how-to-guides/increasing-open-file-limit/) +> If you are using Minikube you will need to enabled the ingress addon as outlined [here](https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/) 1. Clone the repository 2. Navigate to the `gen3-helm/helm/gen3` directory and run `helm dependency update` From 547219746ab1978c8e2e839e64ed7ca6b1a99ab2 Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Fri, 23 Feb 2024 13:54:13 -0700 Subject: [PATCH 34/60] Update docs/global_iam_helm_user.md Co-authored-by: Alexander VanTol --- docs/global_iam_helm_user.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/global_iam_helm_user.md b/docs/global_iam_helm_user.md index e8f68507..70a56376 100644 --- a/docs/global_iam_helm_user.md +++ b/docs/global_iam_helm_user.md @@ -1,4 +1,4 @@ -# AWS Iam Global User +# AWS IAM Global User For Helm code resusability, we have added the functionality to use one iam user for various jobs/services. From c84b65379631cbe73cbd1460010a01590a3f6629 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Tue, 27 Feb 2024 12:53:38 -0700 Subject: [PATCH 35/60] changing the Cluster Secret Stores to Secret Stores to we can have multiple helm charts running in one cluster --- .secrets.baseline | 4 ++-- docs/external_secrets.md | 4 ++-- helm/audit/templates/external-secret.yaml | 4 ++-- .../aws-es-proxy/templates/external-secrets.yaml | 4 ++-- helm/common/templates/_external_secrets.tpl | 12 +++++------- helm/fence/templates/external-secret.yaml | 16 ++++++++-------- helm/gen3/README.md | 5 ++--- helm/gen3/templates/cluster-secret-store.yaml | 4 +--- helm/gen3/values.yaml | 2 -- helm/indexd/templates/external-secrets.yaml | 4 ++-- .../templates/external-secret.yaml | 4 ++-- 11 files changed, 28 insertions(+), 35 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index e4f23d1d..a207dc07 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2024-01-19T22:25:52Z", + "generated_at": "2024-02-27T19:51:16Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -330,7 +330,7 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 221, + "line_number": 219, "type": "Secret Keyword" } ], diff --git a/docs/external_secrets.md b/docs/external_secrets.md index c8dcd5f7..c780dcfb 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -86,7 +86,7 @@ If you would like to only use External Secrets for specific charts, please ensur ## Helm IAM User If you are using a separate IAM user for AWS Secrets Manager please follow the below instructions: -This script Bash script at the beginning of this document should have created a secret titled "NameofIAMuser-user-secret" in your cluster. You will need to retrieve these values to input into your Helm chart for the Cluster Secret Store to authenticate with AWS Secrets Manager. +This script Bash script at the beginning of this document should have created a secret titled "NameofIAMuser-user-secret" in your cluster. You will need to retrieve these values to input into your Helm chart for the Secret Store to authenticate with AWS Secrets Manager. Access Key: @@ -125,7 +125,7 @@ External Secrets relies on three main resources to function properly. (The below secretStoreRef: # The name of the Cluster Secret Store to use. name: {{include "cluster-secret-store" .}} - kind: ClusterSecretStore + kind: SecretStore target: # What Kubernetes secret to create from the secret pulled from AWS Secrets Manager. name: audit-g3auto diff --git a/helm/audit/templates/external-secret.yaml b/helm/audit/templates/external-secret.yaml index f8b3df61..d925feaa 100644 --- a/helm/audit/templates/external-secret.yaml +++ b/helm/audit/templates/external-secret.yaml @@ -6,8 +6,8 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore" .}} - kind: ClusterSecretStore + name: {{include "common.SecretStore" .}} + kind: SecretStore target: name: audit-g3auto creationPolicy: Owner diff --git a/helm/aws-es-proxy/templates/external-secrets.yaml b/helm/aws-es-proxy/templates/external-secrets.yaml index 07d2d4ba..16517911 100644 --- a/helm/aws-es-proxy/templates/external-secrets.yaml +++ b/helm/aws-es-proxy/templates/external-secrets.yaml @@ -6,8 +6,8 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore" .}} - kind: ClusterSecretStore + name: {{include "common.SecretStore" .}} + kind: SecretStore target: name: aws-es-proxy-aws-config creationPolicy: Owner diff --git a/helm/common/templates/_external_secrets.tpl b/helm/common/templates/_external_secrets.tpl index 10a77cb8..f4d7629b 100644 --- a/helm/common/templates/_external_secrets.tpl +++ b/helm/common/templates/_external_secrets.tpl @@ -24,8 +24,8 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore" .}} - kind: ClusterSecretStore + name: {{include "common.SecretStore" .}} + kind: SecretStore target: name: {{ $.Chart.Name }}-dbcreds creationPolicy: Owner @@ -43,7 +43,7 @@ spec: */}} {{ define "common.secretstore" -}} apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore +kind: SecretStore metadata: name: {{.Chart.Name}}-secret-store spec: @@ -56,17 +56,15 @@ spec: accessKeyIDSecretRef: name: {{.Chart.Name}}-aws-config key: access-key - namespace: default secretAccessKeySecretRef: name: {{.Chart.Name}}-aws-config key: secret-access-key - namespace: default {{- end }} {{/* - # Name of the clusterSecretStore + # Name of the SecretStore # We want to allow override here, in case a chart is being deployed without the umbrella chart, # or any other needs to deploy a separate secret store per service. */}} @@ -74,7 +72,7 @@ spec: {{/* Cluster Secret Store for External Secrets */}} -{{- define "common.clusterSecretStore" -}} +{{- define "common.SecretStore" -}} {{- if .Values.global.externalSecrets.separate }} {{- .Chart.Name }}-secret-store {{- else }} diff --git a/helm/fence/templates/external-secret.yaml b/helm/fence/templates/external-secret.yaml index 6a6e661f..27e5ebc3 100644 --- a/helm/fence/templates/external-secret.yaml +++ b/helm/fence/templates/external-secret.yaml @@ -6,8 +6,8 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore" .}} - kind: ClusterSecretStore + name: {{include "common.SecretStore" .}} + kind: SecretStore target: name: fence-jwt-keys creationPolicy: Owner @@ -24,8 +24,8 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore" .}} - kind: ClusterSecretStore + name: {{include "common.SecretStore" .}} + kind: SecretStore target: name: fence-google-app-creds-secret creationPolicy: Owner @@ -42,8 +42,8 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore" .}} - kind: ClusterSecretStore + name: {{include "common.SecretStore" .}} + kind: SecretStore target: name: fence-google-storage-creds-secret creationPolicy: Owner @@ -60,8 +60,8 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore" .}} - kind: ClusterSecretStore + name: {{include "common.SecretStore" .}} + kind: SecretStore target: name: fence-config creationPolicy: Owner diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 65c6aae7..da2afedb 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -96,14 +96,13 @@ Helm chart to deploy Gen3 Data Commons | gitops.json | string | `nil` | multiline string - gitops.json | | gitops.logo | string | `nil` | - logo in base64 | | gitops.sponsors | string | `nil` | | -| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false,"useLocalSecret":{"enabled":false,"localSecretName":null,"localSecretNamespace":null}}` | AWS configuration | +| global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false,"useLocalSecret":{"enabled":false,"localSecretName":null}}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | | global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | -| global.aws.useLocalSecret | map | `{"enabled":false,"localSecretName":null,"localSecretNamespace":null}` | Local secret setting if using a pre-exising secret. | +| global.aws.useLocalSecret | map | `{"enabled":false,"localSecretName":null}` | Local secret setting if using a pre-exising secret. | | global.aws.useLocalSecret.enabled | bool | `false` | Set to true if you would like to use a secret that is already running on your cluster. | | global.aws.useLocalSecret.localSecretName | string | `nil` | Name of the local secret. | -| global.aws.useLocalSecret.localSecretNamespace | string | `nil` | Namespace of the local secret. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.dev | bool | `true` | Deploys postgres/elasticsearch for dev | | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | diff --git a/helm/gen3/templates/cluster-secret-store.yaml b/helm/gen3/templates/cluster-secret-store.yaml index 6251d0fb..5035e4d0 100644 --- a/helm/gen3/templates/cluster-secret-store.yaml +++ b/helm/gen3/templates/cluster-secret-store.yaml @@ -2,7 +2,7 @@ {{ include "common.secretstore" . }} {{- else if .Values.global.aws.useLocalSecret.enabled }} apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore +kind: SecretStore metadata: name: {{.Chart.Name}}-secret-store spec: @@ -15,9 +15,7 @@ spec: accessKeyIDSecretRef: name: {{ .Values.global.aws.useLocalSecret.localSecretName }} key: access-key - namespace: {{ .Values.global.aws.useLocalSecret.localSecretNamespace }} secretAccessKeySecretRef: name: {{ .Values.global.aws.useLocalSecret.localSecretName }} key: secret-access-key - namespace: {{ .Values.global.aws.useLocalSecret.localSecretNamespace }} {{- end }} \ No newline at end of file diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index e3e79684..0037d3ea 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -18,8 +18,6 @@ global: enabled: false # -- (string) Name of the local secret. localSecretName: - # -- (string) Namespace of the local secret. - localSecretNamespace: # -- (bool) Deploys postgres/elasticsearch for dev dev: true postgres: diff --git a/helm/indexd/templates/external-secrets.yaml b/helm/indexd/templates/external-secrets.yaml index 95485e5b..b8cb2a38 100644 --- a/helm/indexd/templates/external-secrets.yaml +++ b/helm/indexd/templates/external-secrets.yaml @@ -8,8 +8,8 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore" .}} - kind: ClusterSecretStore + name: {{include "common.SecretStore" .}} + kind: SecretStore target: name: indexd-service-creds creationPolicy: Owner diff --git a/helm/manifestservice/templates/external-secret.yaml b/helm/manifestservice/templates/external-secret.yaml index af54469f..7d94f5c9 100644 --- a/helm/manifestservice/templates/external-secret.yaml +++ b/helm/manifestservice/templates/external-secret.yaml @@ -6,8 +6,8 @@ metadata: spec: refreshInterval: 5m secretStoreRef: - name: {{include "common.clusterSecretStore" .}} - kind: ClusterSecretStore + name: {{include "common.SecretStore" .}} + kind: SecretStore target: name: manifestservice-g3auto creationPolicy: Owner From b14af763726710d5131d3f1ac6c6fe70e5aa31fc Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Fri, 1 Mar 2024 13:12:09 -0700 Subject: [PATCH 36/60] updating the documentation to more clearly define how to enable external secrets for separate charts or globally --- docs/external_secrets.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index c780dcfb..f019fb86 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -79,9 +79,19 @@ create_iam_user ***Please note that Terraform for the creation and population of Gen3 Secrets in AWS Secrets Manager is in development currently. This Terraform will also create the Iam user and policies necessary to access these secrets.*** ## Enabling External Secrets in Helm charts -To enable External Secrets to be used in a helm chart, you can set the `.Values.global.externalSecrets.deploy` field to "true" for an individual chart or globally by enabling this value in the Gen3 umbrella Helm chart. +Our Helm architecture includes a comprehensive [umbrella](https://github.com/uc-cdis/gen3-helm/tree/master/helm/gen) chart designed to streamline the deployment of external secrets across both the umbrella chart itself and its associated subcharts. By configuring the .Values.global.externalSecrets.deploy setting within this umbrella chart, users can effortlessly initiate the deployment of all related external secret resources. This includes the external secret resources within the subcharts and the secret store required for their management. -If you would like to only use External Secrets for specific charts, please ensure you set `.Values.global.externalSecrets.separate` to "true" in the appropriate charts to ensure a Secret Store can be created to authenticate with AWS Secrets Manager. +#### Global Deployment of External Secrets +Upon deployment of the umbrella chart, the .Values.global.externalSecrets.deploy setting automatically provisions external secret resources for every subchart. This occurs regardless of the individual external secrets deployment settings within subcharts, even if they are explicitly set to false. This feature ensures a unified approach to secret management across all components of the architecture. + +#### Selective Secret Management +For users requiring a more selective application of external secrets — targeting specific secrets while excluding others — the system is designed to accommodate such scenarios with ease. External secret resources will only attempt to replace Kubernetes secrets when a corresponding secret is successfully located within the Secrets Manager. In instances where a specific secret is not found, the External Secrets resource will indicate a SecretSyncedError, signaling the absence of the targeted resource within the Secrets Manager. This is helpful for users want to enabled the use of AWS Secrets Manager for some, but not all the secrets in a specific Helm chart. + +#### Independent Subchart Deployment +In scenarios where subcharts are deployed independently, outside the scope of the umbrella chart, it is crucial to set the .Values.global.externalSecrets.deploy directive within the values.yaml file for each specific service. Additionally, to facilitate the creation of a Secret Store capable of authenticating with AWS Secrets Manager, the .Values.global.externalSecrets.separateSecretStore should be set to true in the relevant charts. This configuration is essential for establishing proper authentication mechanisms for secret retrieval. + +#### Configuring Separate Secret Stores +The .Values.global.externalSecrets.separateSecretStore setting can also be applied within the context of the umbrella chart deployment. Utilizing this setting allows for the creation of distinct Secret Stores dedicated to individual services. This approach is particularly beneficial for environments where it is preferable to limit access to Secrets Manager, ensuring that services only have access to the secrets explicitly required for their operation. ## Helm IAM User If you are using a separate IAM user for AWS Secrets Manager please follow the below instructions: @@ -138,8 +148,6 @@ External Secrets relies on three main resources to function properly. (The below key: {{include "audit-g3auto" .}} ``` -The External Secrets resource will usually fail with "SecretSyncedError" when it cannot find the secret name that is supplied in AWS Secrets Manager. If this happens, the secret may still exist in Kubernetes, but it will not be overwritten by the secret value in AWS Secrets Manager. This is helpful to know if you want to enabled the use of AWS Secrets Manager for some, but not all the secrets in a specific Helm chart. - ## Customizing the AWS Secrets Manager Secrets Name. When pulling a secret from AWS Secrets Manager, you want to ensure that the External Secret resource is referencing the proper name of the secret in AWS Secrets Manager. You can customize the name of the secret to pull from in the `.Values.externalSecrets` section of a Chart. You can see the name for the confiugrable secrets in a chart by looking in this section as well. From cba5b51d96e3b8d474ee35ac196a81bd2149c05b Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Fri, 1 Mar 2024 14:59:04 -0700 Subject: [PATCH 37/60] changing flag "separate" to "separateSecretStore" to be more clear. Also, renaming "cluster-secret-store.yaml" to "secret-store.yaml" due to recent change --- helm/arborist/README.md | 4 ++-- helm/arborist/templates/cluster-secret-store.yaml | 3 --- helm/arborist/templates/secret-store.yaml | 3 +++ helm/arborist/values.yaml | 4 ++-- helm/audit/README.md | 4 ++-- helm/audit/templates/cluster-secret-store.yaml | 3 --- helm/audit/templates/secret-store.yaml | 3 +++ helm/audit/values.yaml | 4 ++-- helm/aws-es-proxy/README.md | 2 +- helm/aws-es-proxy/templates/secret-store.yaml | 3 +++ helm/aws-es-proxy/values.yaml | 4 ++-- helm/common/templates/_external_secrets.tpl | 2 +- helm/fence/README.md | 4 ++-- helm/fence/templates/cluster-secret-store.yaml | 3 --- helm/fence/templates/secret-store.yaml | 3 +++ helm/fence/values.yaml | 4 ++-- helm/indexd/README.md | 4 ++-- helm/indexd/templates/cluster-secret-store.yaml | 3 --- helm/indexd/templates/secret-store.yaml | 3 +++ helm/indexd/values.yaml | 4 ++-- helm/manifestservice/README.md | 4 ++-- helm/manifestservice/templates/cluster-secret-store.yaml | 3 --- helm/manifestservice/templates/secret-store.yaml | 3 +++ helm/manifestservice/values.yaml | 4 ++-- helm/metadata/README.md | 4 ++-- helm/metadata/templates/cluster-secret-store.yaml | 3 --- helm/metadata/templates/secret-store.yaml | 3 +++ helm/metadata/values.yaml | 4 ++-- helm/peregrine/README.md | 4 ++-- helm/peregrine/templates/cluster-secret-store.yaml | 3 --- helm/peregrine/templates/secret-store.yaml | 3 +++ helm/peregrine/values.yaml | 4 ++-- helm/requestor/README.md | 4 ++-- helm/requestor/templates/cluster-secret-store.yaml | 3 --- helm/requestor/templates/secret-store.yaml | 3 +++ helm/requestor/values.yaml | 4 ++-- helm/sheepdog/README.md | 4 ++-- helm/sheepdog/templates/cluster-secret-store.yaml | 3 --- helm/sheepdog/templates/secret-store.yaml | 3 +++ helm/sheepdog/values.yaml | 4 ++-- helm/wts/README.md | 4 ++-- helm/wts/templates/cluster-secret-store.yaml | 3 --- helm/wts/templates/secret-store.yaml | 3 +++ helm/wts/values.yaml | 4 ++-- 44 files changed, 77 insertions(+), 74 deletions(-) delete mode 100644 helm/arborist/templates/cluster-secret-store.yaml create mode 100644 helm/arborist/templates/secret-store.yaml delete mode 100644 helm/audit/templates/cluster-secret-store.yaml create mode 100644 helm/audit/templates/secret-store.yaml create mode 100644 helm/aws-es-proxy/templates/secret-store.yaml delete mode 100644 helm/fence/templates/cluster-secret-store.yaml create mode 100644 helm/fence/templates/secret-store.yaml delete mode 100644 helm/indexd/templates/cluster-secret-store.yaml create mode 100644 helm/indexd/templates/secret-store.yaml delete mode 100644 helm/manifestservice/templates/cluster-secret-store.yaml create mode 100644 helm/manifestservice/templates/secret-store.yaml delete mode 100644 helm/metadata/templates/cluster-secret-store.yaml create mode 100644 helm/metadata/templates/secret-store.yaml delete mode 100644 helm/peregrine/templates/cluster-secret-store.yaml create mode 100644 helm/peregrine/templates/secret-store.yaml delete mode 100644 helm/requestor/templates/cluster-secret-store.yaml create mode 100644 helm/requestor/templates/secret-store.yaml delete mode 100644 helm/sheepdog/templates/cluster-secret-store.yaml create mode 100644 helm/sheepdog/templates/secret-store.yaml delete mode 100644 helm/wts/templates/cluster-secret-store.yaml create mode 100644 helm/wts/templates/secret-store.yaml diff --git a/helm/arborist/README.md b/helm/arborist/README.md index 8e8290e9..c00df2fb 100644 --- a/helm/arborist/README.md +++ b/helm/arborist/README.md @@ -40,9 +40,9 @@ A Helm chart for gen3 arborist | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any arborist secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/arborist/templates/cluster-secret-store.yaml b/helm/arborist/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/arborist/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/arborist/templates/secret-store.yaml b/helm/arborist/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/arborist/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/arborist/values.yaml b/helm/arborist/values.yaml index fd9091f4..c472742f 100644 --- a/helm/arborist/values.yaml +++ b/helm/arborist/values.yaml @@ -63,8 +63,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any arborist secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/audit/README.md b/helm/audit/README.md index 146545ba..03ff4421 100644 --- a/helm/audit/README.md +++ b/helm/audit/README.md @@ -49,9 +49,9 @@ A Helm chart for Kubernetes | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any audit secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/audit/templates/cluster-secret-store.yaml b/helm/audit/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/audit/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/audit/templates/secret-store.yaml b/helm/audit/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/audit/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/audit/values.yaml b/helm/audit/values.yaml index fe372d8a..fe38164c 100644 --- a/helm/audit/values.yaml +++ b/helm/audit/values.yaml @@ -62,8 +62,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any audit secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/aws-es-proxy/README.md b/helm/aws-es-proxy/README.md index 00c6915f..03d37b8d 100644 --- a/helm/aws-es-proxy/README.md +++ b/helm/aws-es-proxy/README.md @@ -35,7 +35,7 @@ A Helm chart for AWS ES Proxy Service for gen3 | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any audit secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.minAvialable | int | `1` | The minimum amount of pods that are available at all times if the PDB is deployed. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | image | map | `{"pullPolicy":"Always","repository":"quay.io/cdis/aws-es-proxy","tag":""}` | Docker image information. | diff --git a/helm/aws-es-proxy/templates/secret-store.yaml b/helm/aws-es-proxy/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/aws-es-proxy/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/aws-es-proxy/values.yaml b/helm/aws-es-proxy/values.yaml index 6f896e48..11c1c200 100644 --- a/helm/aws-es-proxy/values.yaml +++ b/helm/aws-es-proxy/values.yaml @@ -24,8 +24,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any audit secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/common/templates/_external_secrets.tpl b/helm/common/templates/_external_secrets.tpl index f4d7629b..dc9f865b 100644 --- a/helm/common/templates/_external_secrets.tpl +++ b/helm/common/templates/_external_secrets.tpl @@ -73,7 +73,7 @@ spec: Cluster Secret Store for External Secrets */}} {{- define "common.SecretStore" -}} -{{- if .Values.global.externalSecrets.separate }} +{{- if .Values.global.externalSecrets.separateSecretStore }} {{- .Chart.Name }}-secret-store {{- else }} {{- default "gen3-secret-store"}} diff --git a/helm/fence/README.md b/helm/fence/README.md index 7fca9d38..d4a3ef33 100644 --- a/helm/fence/README.md +++ b/helm/fence/README.md @@ -109,9 +109,9 @@ A Helm chart for gen3 Fence | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any fence secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/fence/templates/cluster-secret-store.yaml b/helm/fence/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/fence/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/fence/templates/secret-store.yaml b/helm/fence/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/fence/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/fence/values.yaml b/helm/fence/values.yaml index ec8defd8..2e611279 100644 --- a/helm/fence/values.yaml +++ b/helm/fence/values.yaml @@ -75,8 +75,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any fence secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/indexd/README.md b/helm/indexd/README.md index e73bd8c6..4f07b6ab 100644 --- a/helm/indexd/README.md +++ b/helm/indexd/README.md @@ -39,9 +39,9 @@ A Helm chart for gen3 indexd | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any indexd secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/indexd/templates/cluster-secret-store.yaml b/helm/indexd/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/indexd/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/indexd/templates/secret-store.yaml b/helm/indexd/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/indexd/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/indexd/values.yaml b/helm/indexd/values.yaml index 39f424fc..6d2bd52f 100644 --- a/helm/indexd/values.yaml +++ b/helm/indexd/values.yaml @@ -65,8 +65,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any indexd secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/manifestservice/README.md b/helm/manifestservice/README.md index 8141522d..7f120f2d 100644 --- a/helm/manifestservice/README.md +++ b/helm/manifestservice/README.md @@ -41,9 +41,9 @@ A Helm chart for Kubernetes | global.aws.enabled | bool | `false` | Set to true if deploying to AWS. Controls ingress annotations. | | global.ddEnabled | bool | `false` | Whether Datadog is enabled. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any manifestservice secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.minAvialable | int | `1` | The minimum amount of pods that are available at all times if the PDB is deployed. | | global.pdb | bool | `false` | If the service will be deployed with a Pod Disruption Budget. Note- you need to have more than 2 replicas for the pdb to be deployed. | | image | map | `{"pullPolicy":"Always","repository":"quay.io/cdis/manifestservice","tag":""}` | Docker image information. | diff --git a/helm/manifestservice/templates/cluster-secret-store.yaml b/helm/manifestservice/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/manifestservice/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/manifestservice/templates/secret-store.yaml b/helm/manifestservice/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/manifestservice/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/manifestservice/values.yaml b/helm/manifestservice/values.yaml index 58a0989c..f4c1a2bd 100644 --- a/helm/manifestservice/values.yaml +++ b/helm/manifestservice/values.yaml @@ -25,8 +25,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any manifestservice secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/metadata/README.md b/helm/metadata/README.md index 9bae11bf..d823f844 100644 --- a/helm/metadata/README.md +++ b/helm/metadata/README.md @@ -57,9 +57,9 @@ A Helm chart for gen3 Metadata Service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any metadata secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/metadata/templates/cluster-secret-store.yaml b/helm/metadata/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/metadata/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/metadata/templates/secret-store.yaml b/helm/metadata/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/metadata/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/metadata/values.yaml b/helm/metadata/values.yaml index 82772ef7..84b26e0a 100644 --- a/helm/metadata/values.yaml +++ b/helm/metadata/values.yaml @@ -63,8 +63,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any metadata secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/peregrine/README.md b/helm/peregrine/README.md index 57832ebe..8c83b684 100644 --- a/helm/peregrine/README.md +++ b/helm/peregrine/README.md @@ -40,9 +40,9 @@ A Helm chart for gen3 Peregrine service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any peregrine secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/peregrine/templates/cluster-secret-store.yaml b/helm/peregrine/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/peregrine/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/peregrine/templates/secret-store.yaml b/helm/peregrine/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/peregrine/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/peregrine/values.yaml b/helm/peregrine/values.yaml index 58553889..2cec6c4a 100644 --- a/helm/peregrine/values.yaml +++ b/helm/peregrine/values.yaml @@ -60,8 +60,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any peregrine secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/requestor/README.md b/helm/requestor/README.md index 62a2dc5e..9b4dddec 100644 --- a/helm/requestor/README.md +++ b/helm/requestor/README.md @@ -48,9 +48,9 @@ A Helm chart for gen3 Requestor Service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any requestor secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/requestor/templates/cluster-secret-store.yaml b/helm/requestor/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/requestor/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/requestor/templates/secret-store.yaml b/helm/requestor/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/requestor/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/requestor/values.yaml b/helm/requestor/values.yaml index b172815f..1a060975 100644 --- a/helm/requestor/values.yaml +++ b/helm/requestor/values.yaml @@ -77,8 +77,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any requestor secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/sheepdog/README.md b/helm/sheepdog/README.md index 8d0cc194..cd0c77fd 100644 --- a/helm/sheepdog/README.md +++ b/helm/sheepdog/README.md @@ -49,9 +49,9 @@ A Helm chart for gen3 Sheepdog Service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any sheepdog secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/sheepdog/templates/cluster-secret-store.yaml b/helm/sheepdog/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/sheepdog/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/sheepdog/templates/secret-store.yaml b/helm/sheepdog/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/sheepdog/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/sheepdog/values.yaml b/helm/sheepdog/values.yaml index d95cddeb..420d8ebf 100644 --- a/helm/sheepdog/values.yaml +++ b/helm/sheepdog/values.yaml @@ -63,8 +63,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any sheepdog secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: diff --git a/helm/wts/README.md b/helm/wts/README.md index c951a2d2..b54a6358 100644 --- a/helm/wts/README.md +++ b/helm/wts/README.md @@ -38,9 +38,9 @@ A Helm chart for gen3 workspace token service | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces. Might be used other places too. | -| global.externalSecrets | map | `{"deploy":false,"separate":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"deploy":false,"separateSecretStore":false}` | External Secrets settings. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any wts secrets you have deployed. | -| global.externalSecrets.separate | string | `false` | Will deploy a External Secret Store if deploying this sevice seperately. | +| global.externalSecrets.separateSecretStore | string | `false` | Will deploy a separate External Secret Store for this service. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.kubeBucket | string | `"kube-gen3"` | S3 bucket name for Kubernetes manifest files. | | global.logsBucket | string | `"logs-gen3"` | S3 bucket name for log files. | diff --git a/helm/wts/templates/cluster-secret-store.yaml b/helm/wts/templates/cluster-secret-store.yaml deleted file mode 100644 index 8c1c7717..00000000 --- a/helm/wts/templates/cluster-secret-store.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Values.global.externalSecrets.separate }} -{{ include "common.secretstore" . }} -{{- end }} \ No newline at end of file diff --git a/helm/wts/templates/secret-store.yaml b/helm/wts/templates/secret-store.yaml new file mode 100644 index 00000000..771c7760 --- /dev/null +++ b/helm/wts/templates/secret-store.yaml @@ -0,0 +1,3 @@ +{{ if .Values.global.externalSecrets.separateSecretStore }} +{{ include "common.secretstore" . }} +{{- end }} \ No newline at end of file diff --git a/helm/wts/values.yaml b/helm/wts/values.yaml index 2a440cee..d4e10223 100644 --- a/helm/wts/values.yaml +++ b/helm/wts/values.yaml @@ -63,8 +63,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override any wts secrets you have deployed. deploy: false - # -- (string) Will deploy a External Secret Store if deploying this sevice seperately. - separate: false + # -- (string) Will deploy a separate External Secret Store for this service. + separateSecretStore: false # -- (map) External Secrets settings. externalSecrets: From 4a349673abecb4137b5b5592d4fe3469c709e7d1 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Fri, 1 Mar 2024 15:05:10 -0700 Subject: [PATCH 38/60] pointing doc to master --- docs/PRODUCTION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/PRODUCTION.md b/docs/PRODUCTION.md index ed28c72b..49c5394c 100644 --- a/docs/PRODUCTION.md +++ b/docs/PRODUCTION.md @@ -15,7 +15,7 @@ The postgres and helm charts are included as conditionals in the Gen3 [umbrella ``` ### Kubernetes Configmap and Secret Configuration -For the seamless operation of our services, we utilize Kubernetes secrets. To streamline the integration and management of these secrets, we highly recommend deploying External Secret Manager alongside any existing secret management systems you may already have in place. For a comprehensive guide and best practices on implementing External Secrets within our ecosystem, please consult our dedicated External Secrets Documentation available [here](https://github.com/uc-cdis/gen3-helm/blob/feat/GPE-1032/docs/external_secrets.md). +For the seamless operation of our services, we utilize Kubernetes secrets. To streamline the integration and management of these secrets, we highly recommend deploying External Secret Manager alongside any existing secret management systems you may already have in place. For a comprehensive guide and best practices on implementing External Secrets within our ecosystem, please consult our dedicated External Secrets Documentation available [here](https://github.com/uc-cdis/gen3-helm/blob/master/docs/external_secrets.md). Our services also utilize non-secret configuration variables provided via Kubernetes ConfigMaps. For streamlined management, we advise keeping your values.yaml and configuration files files in source control and utilizing ArgoCD for automatic updates and efficient management of your Gen3 Helm chart. From 339ef9c0b7de76d8988c91e3f53328ebb3057d70 Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:40:33 -0700 Subject: [PATCH 39/60] Update docs/external_secrets.md Co-authored-by: Alexander VanTol --- docs/external_secrets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index f019fb86..19981fe0 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -79,7 +79,7 @@ create_iam_user ***Please note that Terraform for the creation and population of Gen3 Secrets in AWS Secrets Manager is in development currently. This Terraform will also create the Iam user and policies necessary to access these secrets.*** ## Enabling External Secrets in Helm charts -Our Helm architecture includes a comprehensive [umbrella](https://github.com/uc-cdis/gen3-helm/tree/master/helm/gen) chart designed to streamline the deployment of external secrets across both the umbrella chart itself and its associated subcharts. By configuring the .Values.global.externalSecrets.deploy setting within this umbrella chart, users can effortlessly initiate the deployment of all related external secret resources. This includes the external secret resources within the subcharts and the secret store required for their management. +Our Helm architecture includes a comprehensive [umbrella](https://github.com/uc-cdis/gen3-helm/tree/master/helm/gen) chart designed to streamline the deployment of external secrets across both the umbrella chart itself and its associated subcharts. By configuring the `.Values.global.externalSecrets.deploy` setting within this umbrella chart, users can effortlessly initiate the deployment of all related external secret resources. This includes the external secret resources within the subcharts and the secret store required for their management. #### Global Deployment of External Secrets Upon deployment of the umbrella chart, the .Values.global.externalSecrets.deploy setting automatically provisions external secret resources for every subchart. This occurs regardless of the individual external secrets deployment settings within subcharts, even if they are explicitly set to false. This feature ensures a unified approach to secret management across all components of the architecture. From efc7dbb6194a13afb0c71bc4af170142f42dab75 Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:41:06 -0700 Subject: [PATCH 40/60] Update docs/external_secrets.md Co-authored-by: Alexander VanTol --- docs/external_secrets.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index 19981fe0..b43e8929 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -85,7 +85,9 @@ Our Helm architecture includes a comprehensive [umbrella](https://github.com/uc- Upon deployment of the umbrella chart, the .Values.global.externalSecrets.deploy setting automatically provisions external secret resources for every subchart. This occurs regardless of the individual external secrets deployment settings within subcharts, even if they are explicitly set to false. This feature ensures a unified approach to secret management across all components of the architecture. #### Selective Secret Management -For users requiring a more selective application of external secrets — targeting specific secrets while excluding others — the system is designed to accommodate such scenarios with ease. External secret resources will only attempt to replace Kubernetes secrets when a corresponding secret is successfully located within the Secrets Manager. In instances where a specific secret is not found, the External Secrets resource will indicate a SecretSyncedError, signaling the absence of the targeted resource within the Secrets Manager. This is helpful for users want to enabled the use of AWS Secrets Manager for some, but not all the secrets in a specific Helm chart. +For users requiring a more selective application of external secrets — targeting specific secrets while excluding others — the system is designed to accommodate such scenarios with ease. + +External secret resources will only attempt to replace Kubernetes secrets when a corresponding secret is successfully located within the Secrets Manager. In instances where a specific secret is not found, the External Secrets resource will indicate a `SecretSyncedError`, signaling the absence of the targeted resource within the Secrets Manager. This error is acceptable and helpful for users who want to enable the use of AWS Secrets Manager for some, but not all the secrets in a specific Helm chart. #### Independent Subchart Deployment In scenarios where subcharts are deployed independently, outside the scope of the umbrella chart, it is crucial to set the .Values.global.externalSecrets.deploy directive within the values.yaml file for each specific service. Additionally, to facilitate the creation of a Secret Store capable of authenticating with AWS Secrets Manager, the .Values.global.externalSecrets.separateSecretStore should be set to true in the relevant charts. This configuration is essential for establishing proper authentication mechanisms for secret retrieval. From bcc1c5d1ae55af37f4ecaa4cfc6c3f1793f60a89 Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:41:17 -0700 Subject: [PATCH 41/60] Update docs/fence_usersync_job.md Co-authored-by: Alexander VanTol --- docs/fence_usersync_job.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fence_usersync_job.md b/docs/fence_usersync_job.md index dc8d6ea8..6c8f7d74 100644 --- a/docs/fence_usersync_job.md +++ b/docs/fence_usersync_job.md @@ -15,7 +15,7 @@ User lists can be synced from three sources: # S3 user.yaml Setup {#s3-setup} Please see [this](https://github.com/uc-cdis/fence/blob/master/docs/user.yaml_guide.md) documentation that details user.yaml formatting. -You can pull this file from an S3 bucket that is set in the `.Values.usersync.userYamlS3Path` field. Then input the iam credentials for a user that has read access to the specified S3 bucket in the `.Values.secrets.awsAccessKeyId` and `.Values.secrets.awsSecretAccessKey` fields. +You can pull this file from an S3 bucket that is set in the `.Values.usersync.userYamlS3Path` field. Then input the IAM credentials for a user that has read access to the specified S3 bucket in the `.Values.secrets.awsAccessKeyId` and `.Values.secrets.awsSecretAccessKey` fields. You can utilize a local secret to avoid pasting credentials in the values.yaml file. Just set `.global.aws.useLocalSecret.enabled` to true and supply your secret name. From 3c54bba04f46d83869efda24e1da958f61183e1c Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:42:01 -0700 Subject: [PATCH 42/60] Update docs/fence_usersync_job.md Co-authored-by: Alexander VanTol --- docs/fence_usersync_job.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fence_usersync_job.md b/docs/fence_usersync_job.md index 6c8f7d74..214ebebc 100644 --- a/docs/fence_usersync_job.md +++ b/docs/fence_usersync_job.md @@ -20,7 +20,7 @@ You can pull this file from an S3 bucket that is set in the `.Values.usersync.us You can utilize a local secret to avoid pasting credentials in the values.yaml file. Just set `.global.aws.useLocalSecret.enabled` to true and supply your secret name. ***Notice: -The Gen3 Helm chart has various jobs and uses for an Iam user. To enhance code reusability, we've implemented the option for jobs and services to share the same AWS IAM global user. If you would like to use the same Iam user for Fence Usersync, External Secrets, etc.- you can follow [THIS](global_iam_helm_user.md) guide that details how to setup a Helm global user.*** +The Gen3 Helm chart has various jobs and uses for an IAM user. To enhance code reusability, we've implemented the option for jobs and services to share the same AWS IAM global user. If you would like to use the same IAM user for Fence Usersync, External Secrets, etc.- you can follow [THIS](global_iam_helm_user.md) guide that details how to setup a Helm global user.*** As previously mentioned, if the `.Values.usersync.userYamlS3Path` string is set to "none", the user.yaml file from Fence values.yaml will be used. From 792a06163420549038be5776f808a628ed19df32 Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:42:09 -0700 Subject: [PATCH 43/60] Update docs/global_iam_helm_user.md Co-authored-by: Alexander VanTol --- docs/global_iam_helm_user.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/global_iam_helm_user.md b/docs/global_iam_helm_user.md index 70a56376..e2a35d9c 100644 --- a/docs/global_iam_helm_user.md +++ b/docs/global_iam_helm_user.md @@ -1,6 +1,6 @@ # AWS IAM Global User -For Helm code resusability, we have added the functionality to use one iam user for various jobs/services. +For Helm code reusability, we have added the functionality to use one IAM user for various jobs/services. We are currently in the process of integrating this user into our Terraform code. In the meantime, you can manually create a global user by referring to this guide. From 4f69cf335694ea26ce957fc5a50d2eb8deee2aa5 Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:43:12 -0700 Subject: [PATCH 44/60] Update docs/external_secrets.md Co-authored-by: Alexander VanTol --- docs/external_secrets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index b43e8929..3c0102e0 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -107,7 +107,7 @@ kubectl get secret "your secret name" -o jsonpath="{.data.access-key}" | base64 ``` -Secret Access Key +Secret Access Key: ``` kubectl get secret "your secret name" -o jsonpath="{.data.secret-access-key}" | base64 --decode ``` From de399c0d2401cc34660cb7b7e0180221fc882f5c Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:43:23 -0700 Subject: [PATCH 45/60] Update docs/external_secrets.md Co-authored-by: Alexander VanTol --- docs/external_secrets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index 3c0102e0..8b1605ab 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -82,7 +82,7 @@ create_iam_user Our Helm architecture includes a comprehensive [umbrella](https://github.com/uc-cdis/gen3-helm/tree/master/helm/gen) chart designed to streamline the deployment of external secrets across both the umbrella chart itself and its associated subcharts. By configuring the `.Values.global.externalSecrets.deploy` setting within this umbrella chart, users can effortlessly initiate the deployment of all related external secret resources. This includes the external secret resources within the subcharts and the secret store required for their management. #### Global Deployment of External Secrets -Upon deployment of the umbrella chart, the .Values.global.externalSecrets.deploy setting automatically provisions external secret resources for every subchart. This occurs regardless of the individual external secrets deployment settings within subcharts, even if they are explicitly set to false. This feature ensures a unified approach to secret management across all components of the architecture. +Upon deployment of the umbrella chart, the `.Values.global.externalSecrets.deploy` setting automatically provisions external secret resources for every subchart. This occurs regardless of the individual external secrets deployment settings within subcharts, even if they are explicitly set to `false`. This feature ensures a unified approach to secret management across all components of the architecture. #### Selective Secret Management For users requiring a more selective application of external secrets — targeting specific secrets while excluding others — the system is designed to accommodate such scenarios with ease. From 89d3686ff2da86bd76325821d040ea0feb69c0dd Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 4 Mar 2024 11:33:15 -0700 Subject: [PATCH 46/60] adding default values to the external secrets install script --- docs/external_secrets.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index 8b1605ab..4f2c506d 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -14,9 +14,9 @@ The Gen3 Helm chart has various jobs and uses for an IAM user. To enhance code r #!/bin/bash AWS_ACCOUNT="" -region="" -iam_policy="" -iam_user="" +region="us-east-1" +iam_policy="external_secrets_policy" +iam_user="external_secrets_user" helm_install() { From 6367637063c2b17fb49ee4478f1037eadbae7241 Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:33:33 -0700 Subject: [PATCH 47/60] Update docs/external_secrets.md Co-authored-by: Alexander VanTol --- docs/external_secrets.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index 4f2c506d..d6ef0ec3 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -90,7 +90,9 @@ For users requiring a more selective application of external secrets — targeti External secret resources will only attempt to replace Kubernetes secrets when a corresponding secret is successfully located within the Secrets Manager. In instances where a specific secret is not found, the External Secrets resource will indicate a `SecretSyncedError`, signaling the absence of the targeted resource within the Secrets Manager. This error is acceptable and helpful for users who want to enable the use of AWS Secrets Manager for some, but not all the secrets in a specific Helm chart. #### Independent Subchart Deployment -In scenarios where subcharts are deployed independently, outside the scope of the umbrella chart, it is crucial to set the .Values.global.externalSecrets.deploy directive within the values.yaml file for each specific service. Additionally, to facilitate the creation of a Secret Store capable of authenticating with AWS Secrets Manager, the .Values.global.externalSecrets.separateSecretStore should be set to true in the relevant charts. This configuration is essential for establishing proper authentication mechanisms for secret retrieval. +In scenarios where subcharts are deployed independently, outside the scope of the umbrella chart, it is crucial to set the `.Values.global.externalSecrets.deploy` directive within the `values.yaml` file for each specific service. + +Additionally, to facilitate the creation of a Secret Store capable of authenticating with AWS Secrets Manager, the `.Values.global.externalSecrets.separateSecretStore` should be set to true in the relevant charts. This configuration is essential for establishing proper authentication mechanisms for secret retrieval. #### Configuring Separate Secret Stores The .Values.global.externalSecrets.separateSecretStore setting can also be applied within the context of the umbrella chart deployment. Utilizing this setting allows for the creation of distinct Secret Stores dedicated to individual services. This approach is particularly beneficial for environments where it is preferable to limit access to Secrets Manager, ensuring that services only have access to the secrets explicitly required for their operation. From 013e420a6d2e0e540665e21d9317574529917378 Mon Sep 17 00:00:00 2001 From: EliseCastle23 <109446148+EliseCastle23@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:33:46 -0700 Subject: [PATCH 48/60] Update docs/external_secrets.md Co-authored-by: Alexander VanTol --- docs/external_secrets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index d6ef0ec3..96a30909 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -95,7 +95,7 @@ In scenarios where subcharts are deployed independently, outside the scope of th Additionally, to facilitate the creation of a Secret Store capable of authenticating with AWS Secrets Manager, the `.Values.global.externalSecrets.separateSecretStore` should be set to true in the relevant charts. This configuration is essential for establishing proper authentication mechanisms for secret retrieval. #### Configuring Separate Secret Stores -The .Values.global.externalSecrets.separateSecretStore setting can also be applied within the context of the umbrella chart deployment. Utilizing this setting allows for the creation of distinct Secret Stores dedicated to individual services. This approach is particularly beneficial for environments where it is preferable to limit access to Secrets Manager, ensuring that services only have access to the secrets explicitly required for their operation. +The `.Values.global.externalSecrets.separateSecretStore` setting can also be applied within the context of the umbrella chart deployment. Utilizing this setting allows for the creation of distinct Secret Stores dedicated to individual services. This approach is particularly beneficial for environments where it is preferable to limit access to Secrets Manager, ensuring that services only have access to the secrets explicitly required for their operation. ## Helm IAM User If you are using a separate IAM user for AWS Secrets Manager please follow the below instructions: From a49d333ae7a4fb708a5d9d523e9e9021dfce8ded Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 4 Mar 2024 11:40:22 -0700 Subject: [PATCH 49/60] adding links to examples of resouces for the "How External Secrets Works" section of the md file --- docs/external_secrets.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/external_secrets.md b/docs/external_secrets.md index 96a30909..a93353c1 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -122,9 +122,9 @@ Please note that only some Helm charts are compatible with External Secrets curr ## How External Secrets Works. External Secrets relies on three main resources to function properly. (The below have links to examples of each resource) -1. Aws-config- Contains Access and Secret Access keys used by the Cluster Secret Store to authenticate with AWS Secrets Manager -2. Cluster Secret Store- Resource to Authenticate with AWS Secrets Manager -3. External Secret- References the Secret Store and is used as a "map" to tell External Secrets Operator what secret to grab from External Secrets and the name of the Kubernetes Secret to create locally. +1. [Aws-config](https://github.com/uc-cdis/gen3-helm/blob/master/helm/common/templates/_aws_config.tpl)- Contains Access and Secret Access keys used by the Cluster Secret Store to authenticate with AWS Secrets Manager +2. [Secret Store](https://github.com/uc-cdis/gen3-helm/blob/master/helm/common/templates/_external_secrets.tpl#L41-L62)- Resource to Authenticate with AWS Secrets Manager +3. [External Secret](https://github.com/uc-cdis/gen3-helm/blob/master/helm/common/templates/_external_secrets.tpl#L15-L38)- References the Secret Store and is used as a "map" to tell External Secrets Operator what secret to grab from External Secrets and the name of the Kubernetes Secret to create locally. Anatomy of an ExternalSecret: ``` @@ -137,7 +137,7 @@ External Secrets relies on three main resources to function properly. (The below #How often to Sync with AWS Secrets Manager refreshInterval: 5m secretStoreRef: - # The name of the Cluster Secret Store to use. + # The name of the Secret Store to use. name: {{include "cluster-secret-store" .}} kind: SecretStore target: From bafcd7ffad4da5884d86a99c7925e3d1b6034eda Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 4 Mar 2024 11:44:04 -0700 Subject: [PATCH 50/60] adding commands to the README to install nginx ingress --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index d56d16ec..364a65d7 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,14 @@ For local development you must be connected to a kubernetes cluster. As referenc For MacOS users, [Minikube](https://minikube.sigs.k8s.io/docs/start/) equipped with the ingress addon serves as a viable alternative to Rancher Desktop. On Linux, we've observed that using [Kind](https://kind.sigs.k8s.io/) with an NGINX ingress installed often provides a more seamless experience compared to both Rancher Desktop and Minikube. Essentially, Helm requires access to a Kubernetes cluster with ingress capabilities, facilitating the loading of the portal in your browser for an optimal development workflow. +To install the NGINX ingress: +``` + helm repo add nginx-stable https://helm.nginx.com/stable + helm repo update + kubectl create ns nginx-ingress + helm install nginx-ingress nginx-stable/nginx-ingress --namespace nginx-ingress +``` + > **Warning** > If you are using Rancher Desktop you need to increase the vm.max_map_count as outlined [here](https://docs.rancherdesktop.io/how-to-guides/increasing-open-file-limit/) > If you are using Minikube you will need to enabled the ingress addon as outlined [here](https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/) From 98c677f93d84e7ee8a4b0a0835c8922b41756d3a Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 4 Mar 2024 11:53:24 -0700 Subject: [PATCH 51/60] adding in External Secrets Lucid chart --- docs/PRODUCTION.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/PRODUCTION.md b/docs/PRODUCTION.md index 49c5394c..4a6aead0 100644 --- a/docs/PRODUCTION.md +++ b/docs/PRODUCTION.md @@ -21,3 +21,5 @@ Our services also utilize non-secret configuration variables provided via Kubern Each service is designed to seamlessly integrate and manage the combination of Kubernetes secrets and ConfigMaps, ensuring the encapsulated information is effectively injected into the underlying application. +Please see the diagram provided [here](https://lucid.app/lucidchart/f0e9baf8-9179-4be0-ae65-182ed891df22/edit?invitationId=inv_83c83c6a-0f1d-4236-a13e-3131c1fc851f&page=TDBgA8eMNr7J#) that details how External Secrets operates. We also mention the use of Argo CD as our choice option for Helm deployments. + From 6b4c7f6a0830a07b1540d6672b7af2a38dee053c Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Tue, 5 Mar 2024 14:04:57 -0700 Subject: [PATCH 52/60] adding in embedded lucidchart image. changing logic so db creds can get created even if external secrets is enabled. --- docs/PRODUCTION.md | 3 ++- docs/images/lucidChart.png | Bin 0 -> 154619 bytes helm/arborist/templates/db-init.yaml | 2 -- helm/audit/templates/db-init.yaml | 2 -- helm/common/templates/_db_setup_job.tpl | 2 -- helm/fence/templates/db-init.yaml | 2 -- helm/fence/templates/fence-config.yaml | 4 +--- helm/indexd/templates/db-init.yaml | 2 -- helm/indexd/templates/indexd-secret.yaml | 4 +--- helm/peregrine/templates/db-init.yaml | 2 -- helm/requestor/templates/db-init.yaml | 2 -- helm/sheepdog/README.md | 4 ++-- helm/sheepdog/values.yaml | 2 +- helm/wts/templates/db-init.yaml | 2 -- 14 files changed, 7 insertions(+), 26 deletions(-) create mode 100644 docs/images/lucidChart.png diff --git a/docs/PRODUCTION.md b/docs/PRODUCTION.md index 4a6aead0..c15bd388 100644 --- a/docs/PRODUCTION.md +++ b/docs/PRODUCTION.md @@ -21,5 +21,6 @@ Our services also utilize non-secret configuration variables provided via Kubern Each service is designed to seamlessly integrate and manage the combination of Kubernetes secrets and ConfigMaps, ensuring the encapsulated information is effectively injected into the underlying application. -Please see the diagram provided [here](https://lucid.app/lucidchart/f0e9baf8-9179-4be0-ae65-182ed891df22/edit?invitationId=inv_83c83c6a-0f1d-4236-a13e-3131c1fc851f&page=TDBgA8eMNr7J#) that details how External Secrets operates. We also mention the use of Argo CD as our choice option for Helm deployments. +Please see the diagram provided that details how External Secrets operates. We also mention the use of Argo CD as our choice option for Helm deployments. +![External Secrets Diagram](./images/lucidChart.png "Helm Secrets Manager") diff --git a/docs/images/lucidChart.png b/docs/images/lucidChart.png new file mode 100644 index 0000000000000000000000000000000000000000..dbb986c463f55364cfabd46d595ec957890c7741 GIT binary patch literal 154619 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�`!@>dvDerA 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 literal 0 HcmV?d00001 diff --git a/helm/arborist/templates/db-init.yaml b/helm/arborist/templates/db-init.yaml index 56e1ea41..5ef14e87 100644 --- a/helm/arborist/templates/db-init.yaml +++ b/helm/arborist/templates/db-init.yaml @@ -1,6 +1,4 @@ -{{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} -{{- end }} --- {{ include "common.db_setup_job" . }} --- diff --git a/helm/audit/templates/db-init.yaml b/helm/audit/templates/db-init.yaml index 56e1ea41..5ef14e87 100644 --- a/helm/audit/templates/db-init.yaml +++ b/helm/audit/templates/db-init.yaml @@ -1,6 +1,4 @@ -{{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} -{{- end }} --- {{ include "common.db_setup_job" . }} --- diff --git a/helm/common/templates/_db_setup_job.tpl b/helm/common/templates/_db_setup_job.tpl index d1f49c1f..af90d9e8 100644 --- a/helm/common/templates/_db_setup_job.tpl +++ b/helm/common/templates/_db_setup_job.tpl @@ -170,7 +170,6 @@ Create k8s secrets for connecting to postgres */}} # DB Secrets {{- define "common.db-secret" -}} -{{- if not .Values.global.externalSecrets.deploy }} apiVersion: v1 kind: Secret metadata: @@ -185,5 +184,4 @@ data: {{- else }} host: {{ ( $.Values.postgres.host | default ( $.Values.global.postgres.master.host)) | b64enc | quote }} {{- end }} -{{- end }} {{- end }} \ No newline at end of file diff --git a/helm/fence/templates/db-init.yaml b/helm/fence/templates/db-init.yaml index 56e1ea41..5ef14e87 100644 --- a/helm/fence/templates/db-init.yaml +++ b/helm/fence/templates/db-init.yaml @@ -1,6 +1,4 @@ -{{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} -{{- end }} --- {{ include "common.db_setup_job" . }} --- diff --git a/helm/fence/templates/fence-config.yaml b/helm/fence/templates/fence-config.yaml index e50568ee..29d0df2e 100644 --- a/helm/fence/templates/fence-config.yaml +++ b/helm/fence/templates/fence-config.yaml @@ -1,4 +1,3 @@ -{{ if not .Values.global.externalSecrets.deploy }} apiVersion: v1 kind: Secret metadata: @@ -9,5 +8,4 @@ stringData: {{- with .Values.FENCE_CONFIG }} {{- toYaml . | nindent 4 }} {{ end }} ---- -{{- end }} \ No newline at end of file +--- \ No newline at end of file diff --git a/helm/indexd/templates/db-init.yaml b/helm/indexd/templates/db-init.yaml index d25e1779..0393aa73 100644 --- a/helm/indexd/templates/db-init.yaml +++ b/helm/indexd/templates/db-init.yaml @@ -1,6 +1,4 @@ -{{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} -{{- end }} --- {{ include "common.db_setup_sa" . }} --- diff --git a/helm/indexd/templates/indexd-secret.yaml b/helm/indexd/templates/indexd-secret.yaml index a970e9a1..12ab5364 100644 --- a/helm/indexd/templates/indexd-secret.yaml +++ b/helm/indexd/templates/indexd-secret.yaml @@ -6,7 +6,6 @@ type: Opaque data: {{ (.Files.Glob "indexd-settings/*").AsSecrets | indent 2 }} --- -{{ if not .Values.global.externalSecrets.deploy }} apiVersion: v1 kind: Secret metadata: @@ -14,5 +13,4 @@ metadata: type: Opaque data: fence: {{ include "common.getOrGenSecret" (list .Values.secrets.userdb.fence "indexd-service-creds" "fence" 20 .Release.Namespace) }} - sheepdog: {{ include "common.getOrGenSecret" (list .Values.secrets.userdb.sheepdog "indexd-service-creds" "sheepdog" 20 .Release.Namespace) }} -{{- end }} \ No newline at end of file + sheepdog: {{ include "common.getOrGenSecret" (list .Values.secrets.userdb.sheepdog "indexd-service-creds" "sheepdog" 20 .Release.Namespace) }} \ No newline at end of file diff --git a/helm/peregrine/templates/db-init.yaml b/helm/peregrine/templates/db-init.yaml index 56e1ea41..5ef14e87 100644 --- a/helm/peregrine/templates/db-init.yaml +++ b/helm/peregrine/templates/db-init.yaml @@ -1,6 +1,4 @@ -{{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} -{{- end }} --- {{ include "common.db_setup_job" . }} --- diff --git a/helm/requestor/templates/db-init.yaml b/helm/requestor/templates/db-init.yaml index 56e1ea41..5ef14e87 100644 --- a/helm/requestor/templates/db-init.yaml +++ b/helm/requestor/templates/db-init.yaml @@ -1,6 +1,4 @@ -{{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} -{{- end }} --- {{ include "common.db_setup_job" . }} --- diff --git a/helm/sheepdog/README.md b/helm/sheepdog/README.md index cd0c77fd..bb94c74b 100644 --- a/helm/sheepdog/README.md +++ b/helm/sheepdog/README.md @@ -69,10 +69,10 @@ A Helm chart for gen3 Sheepdog Service | global.publicDataSets | bool | `true` | Whether public datasets are enabled. | | global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | ARN of the reverse proxy certificate. | | global.tierAccessLevel | string | `"libre"` | Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` | -| image | map | `{"pullPolicy":"Always","repository":"quay.io/cdis/sheepdog","tag":"helm-test"}` | Docker image information. | +| image | map | `{"pullPolicy":"Always","repository":"quay.io/cdis/sheepdog","tag":""}` | Docker image information. | | image.pullPolicy | string | `"Always"` | Docker pull policy. | | image.repository | string | `"quay.io/cdis/sheepdog"` | Docker repository. | -| image.tag | string | `"helm-test"` | Overrides the image tag whose default is the chart appVersion. | +| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. | | indexdUrl | string | `"http://indexd-service"` | URL for the indexd service | | partOf | string | `"Core-Service"` | Label to help organize pods and their use. Any value is valid, but use "_" or "-" to divide words. | | podAnnotations | map | `{"gen3.io/network-ingress":"sheepdog"}` | Annotations to add to the pod | diff --git a/helm/sheepdog/values.yaml b/helm/sheepdog/values.yaml index 420d8ebf..30291645 100644 --- a/helm/sheepdog/values.yaml +++ b/helm/sheepdog/values.yaml @@ -168,7 +168,7 @@ image: # -- (string) Docker pull policy. pullPolicy: Always # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: "helm-test" + tag: "" # Environment Variables # -- (string) URL of the data dictionary. diff --git a/helm/wts/templates/db-init.yaml b/helm/wts/templates/db-init.yaml index 1e55878d..d99ca1b2 100644 --- a/helm/wts/templates/db-init.yaml +++ b/helm/wts/templates/db-init.yaml @@ -1,6 +1,4 @@ -{{- if not .Values.global.externalSecrets.deploy }} {{ include "common.db-secret" . }} -{{- end }} --- {{ include "common.db_setup_job" . }} --- From da2e79b78ff866fec98f1e8e5a5a6e12877e56f3 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 7 Mar 2024 08:31:35 -0700 Subject: [PATCH 53/60] removing empty values from gen3 values.yaml file --- .secrets.baseline | 4 +- helm/gen3/README.md | 71 +------------------- helm/gen3/values.yaml | 146 +----------------------------------------- 3 files changed, 4 insertions(+), 217 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index a207dc07..02c4f488 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2024-02-27T19:51:16Z", + "generated_at": "2024-03-07T15:30:30Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -330,7 +330,7 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 219, + "line_number": 164, "type": "Secret Keyword" } ], diff --git a/helm/gen3/README.md b/helm/gen3/README.md index da2afedb..36814cfc 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -48,41 +48,20 @@ Helm chart to deploy Gen3 Data Commons | Key | Type | Default | Description | |-----|------|---------|-------------| | ambassador.enabled | bool | `true` | Whether to deploy the ambassador subchart. | -| ambassador.image.repository | string | `nil` | The Docker image repository for the ambassador service. | -| ambassador.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | arborist.enabled | bool | `true` | Whether to deploy the arborist subchart. | -| arborist.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| arborist.image.repository | string | `nil` | The Docker image repository for the arborist service. | -| arborist.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | argo-wrapper.enabled | bool | `true` | Whether to deploy the argo-wrapper subchart. | -| argo-wrapper.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| argo-wrapper.image.repository | string | `nil` | The Docker image repository for the argo-wrapper service. | -| argo-wrapper.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | audit.enabled | bool | `true` | Whether to deploy the audit subchart. | -| audit.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| audit.image.repository | string | `nil` | The Docker image repository for the audit service. | -| audit.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | aws-es-proxy.enabled | bool | `false` | Whether to deploy the aws-es-proxy subchart. | | aws-es-proxy.esEndpoint | str | `"test.us-east-1.es.amazonaws.com"` | Elasticsearch endpoint in AWS | -| aws-es-proxy.secrets | map | `{"awsAccessKeyId":"","awsSecretAccessKey":""}` | Secret information | -| aws-es-proxy.secrets.awsAccessKeyId | str | `""` | AWS access key ID for aws-es-proxy | -| aws-es-proxy.secrets.awsSecretAccessKey | str | `""` | AWS secret access key for aws-es-proxy | | elasticsearch.clusterHealthCheckParams | string | `"wait_for_status=yellow&timeout=1s"` | | | elasticsearch.clusterName | string | `"gen3-elasticsearch"` | | -| elasticsearch.esConfig."elasticsearch.yml" | string | `"# Here we can add elasticsearch config\n"` | | | elasticsearch.maxUnavailable | int | `0` | | | elasticsearch.replicas | int | `1` | | | elasticsearch.singleNode | bool | `true` | | | etl.enabled | bool | `true` | Whether to deploy the etl subchart. | -| fence.FENCE_CONFIG | map | `nil` | Configuration settings for Fence app | -| fence.USER_YAML | string | `nil` | USER YAML. Passed in as a multiline string. | | fence.enabled | bool | `true` | Whether to deploy the fence subchart. | -| fence.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| fence.image.repository | string | `nil` | The Docker image repository for the fence service. | -| fence.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | -| fence.usersync | map | `{"addDbgap":false,"custom_image":null,"onlyDbgap":false,"schedule":"*/30 * * * *","slack_send_dbgap":false,"slack_webhook":"None","syncFromDbgap":false,"userYamlS3Path":"s3://cdis-gen3-users/helm-test/user.yaml","usersync":false}` | Configuration options for usersync cronjob. | +| fence.usersync | map | `{"addDbgap":false,"onlyDbgap":false,"schedule":"*/30 * * * *","slack_send_dbgap":false,"slack_webhook":"None","syncFromDbgap":false,"userYamlS3Path":"s3://cdis-gen3-users/helm-test/user.yaml","usersync":false}` | Configuration options for usersync cronjob. | | fence.usersync.addDbgap | bool | `false` | Force attempting a dbgap sync if "true", falls back on user.yaml | -| fence.usersync.custom_image | string | `nil` | To set a custom image for pulling the user.yaml file from S3. Default is the Gen3 Awshelper image. | | fence.usersync.onlyDbgap | bool | `false` | Forces ONLY a dbgap sync if "true", IGNORING user.yaml | | fence.usersync.schedule | string | `"*/30 * * * *"` | The cron schedule expression to use in the usersync cronjob. Runs every 30 minutes by default. | | fence.usersync.slack_send_dbgap | bool | `false` | Will echo what files we are seeing on dbgap ftp to Slack. | @@ -90,12 +69,6 @@ Helm chart to deploy Gen3 Data Commons | fence.usersync.syncFromDbgap | bool | `false` | Whether to sync data from dbGaP. | | fence.usersync.userYamlS3Path | string | `"s3://cdis-gen3-users/helm-test/user.yaml"` | Path to the user.yaml file in S3. | | fence.usersync.usersync | bool | `false` | Whether to run Fence usersync or not. | -| gitops.createdby | string | `nil` | - createdby.png - base64 | -| gitops.css | string | `nil` | - multiline string - gitops.css | -| gitops.favicon | string | `nil` | - favicon in base64 | -| gitops.json | string | `nil` | multiline string - gitops.json | -| gitops.logo | string | `nil` | - logo in base64 | -| gitops.sponsors | string | `nil` | | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false,"useLocalSecret":{"enabled":false,"localSecretName":null}}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | @@ -123,9 +96,6 @@ Helm chart to deploy Gen3 Data Commons | global.tierAccessLevel | string | `"libre"` | Access level for tiers. acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` | | global.tierAccessLimit | int | `"1000"` | Only relevant if tireAccessLevel is set to "regular". Summary charts below this limit will not appear for aggregated data. | | guppy.enabled | bool | `false` | Whether to deploy the guppy subchart. | -| guppy.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| guppy.image.repository | string | `nil` | The Docker image repository for the guppy service. | -| guppy.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | hatchery.enabled | bool | `true` | Whether to deploy the hatchery subchart. | | hatchery.hatchery.containers[0].args[0] | string | `"--NotebookApp.base_url=/lw-workspace/proxy/"` | | | hatchery.hatchery.containers[0].args[1] | string | `"--NotebookApp.default_url=/lab"` | | @@ -150,7 +120,6 @@ Helm chart to deploy Gen3 Data Commons | hatchery.hatchery.containers[0].use-tls | string | `"false"` | | | hatchery.hatchery.containers[0].user-uid | int | `1000` | | | hatchery.hatchery.containers[0].user-volume-location | string | `"/home/jovyan/pd"` | | -| hatchery.hatchery.sidecarContainer.args | list | `[]` | Arguments to pass to the sidecare container. | | hatchery.hatchery.sidecarContainer.command | list | `["/bin/bash","./sidecar.sh"]` | Commands to run for the sidecar container. | | hatchery.hatchery.sidecarContainer.cpu-limit | string | `"0.1"` | The maximum amount of CPU the sidecar container can use | | hatchery.hatchery.sidecarContainer.env | map | `{"HOSTNAME":"{{ .Values.global.hostname }}","NAMESPACE":"{{ .Release.Namespace }}"}` | Environment variables to pass to the sidecar container | @@ -162,60 +131,22 @@ Helm chart to deploy Gen3 Data Commons | hatchery.hatchery.sidecarContainer.lifecycle-pre-stop[4] | string | `"/bin/sh"` | | | hatchery.hatchery.sidecarContainer.lifecycle-pre-stop[5] | string | `"root"` | | | hatchery.hatchery.sidecarContainer.memory-limit | string | `"256Mi"` | The maximum amount of memory the sidecar container can use | -| hatchery.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| hatchery.image.repository | string | `nil` | The Docker image repository for the hatchery service. | -| hatchery.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | indexd.defaultPrefix | string | `"PREFIX/"` | the default prefix for indexd records | | indexd.enabled | bool | `true` | Whether to deploy the indexd subchart. | -| indexd.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| indexd.image.repository | string | `nil` | The Docker image repository for the indexd service. | -| indexd.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | manifestservice.enabled | bool | `true` | Whether to deploy the manifest service subchart. | -| manifestservice.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| manifestservice.image.repository | string | `nil` | The Docker image repository for the manifest service service. | -| manifestservice.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | metadata.enabled | bool | `true` | Whether to deploy the metadata subchart. | -| metadata.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| metadata.image.repository | string | `nil` | The Docker image repository for the metadata service. | -| metadata.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | peregrine.enabled | bool | `true` | Whether to deploy the peregrine subchart. | -| peregrine.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| peregrine.image.repository | string | `nil` | The Docker image repository for the peregrine service. | -| peregrine.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | pidgin.enabled | bool | `true` | Whether to deploy the pidgin subchart. | -| pidgin.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| pidgin.image.repository | string | `nil` | The Docker image repository for the pidgin service. | -| pidgin.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | portal.enabled | bool | `true` | Whether to deploy the portal subchart. | -| portal.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| portal.image.repository | string | `nil` | The Docker image repository for the portal service. | -| portal.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | postgresql.primary.persistence.enabled | bool | `false` | Option to persist the dbs data. | | requestor.enabled | bool | `false` | Whether to deploy the requestor subchart. | -| requestor.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| requestor.image.repository | string | `nil` | The Docker image repository for the requestor service. | -| requestor.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | revproxy.enabled | bool | `true` | Whether to deploy the revproxy subchart. | -| revproxy.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| revproxy.image.repository | string | `nil` | The Docker image repository for the revproxy service. | -| revproxy.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | -| revproxy.ingress.annotations | map | `{}` | Annotations to add to the ingress. | -| revproxy.ingress.className | string | `""` | The ingress class name. | | revproxy.ingress.enabled | bool | `false` | Whether to create the custom revproxy ingress | | revproxy.ingress.hosts | list | `[{"host":"chart-example.local"}]` | Where to route the traffic. | | revproxy.ingress.tls | list | `[]` | To secure an Ingress by specifying a secret that contains a TLS private key and certificate. | | sheepdog.enabled | bool | `true` | Whether to deploy the sheepdog subchart. | -| sheepdog.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| sheepdog.image.repository | string | `nil` | The Docker image repository for the sheepdog service. | -| sheepdog.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | ssjdispatcher.enabled | bool | `false` | Whether to deploy the ssjdispatcher subchart. | -| ssjdispatcher.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| ssjdispatcher.image.repository | string | `nil` | The Docker image repository for the ssjdispatcher service. | -| ssjdispatcher.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | | wts.enabled | bool | `true` | Whether to deploy the wts subchart. | -| wts.image | map | `{"repository":null,"tag":null}` | Docker image information. | -| wts.image.repository | string | `nil` | The Docker image repository for the wts service. | -| wts.image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. | ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index 0037d3ea..79eeb0a6 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -66,41 +66,18 @@ global: ambassador: # -- (bool) Whether to deploy the ambassador subchart. enabled: true - image: - # -- (string) The Docker image repository for the ambassador service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: arborist: # -- (bool) Whether to deploy the arborist subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the arborist service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: argo-wrapper: # -- (bool) Whether to deploy the argo-wrapper subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the argo-wrapper service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: audit: # -- (bool) Whether to deploy the audit subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the audit service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: aws-es-proxy: @@ -108,12 +85,6 @@ aws-es-proxy: enabled: false # -- (str) Elasticsearch endpoint in AWS esEndpoint: test.us-east-1.es.amazonaws.com - # -- (map) Secret information - secrets: - # -- (str) AWS access key ID for aws-es-proxy - awsAccessKeyId: "" - # -- (str) AWS secret access key for aws-es-proxy - awsSecretAccessKey: "" etl: # -- (bool) Whether to deploy the etl subchart. @@ -122,24 +93,12 @@ etl: fence: # -- (bool) Whether to deploy the fence subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the fence service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: - # -- (map) Configuration settings for Fence app - FENCE_CONFIG: - # -- (string) USER YAML. Passed in as a multiline string. - USER_YAML: # -- (map) Configuration options for usersync cronjob. usersync: # -- (bool) Whether to run Fence usersync or not. usersync: false # -- (string) The cron schedule expression to use in the usersync cronjob. Runs every 30 minutes by default. schedule: "*/30 * * * *" - # -- (string) To set a custom image for pulling the user.yaml file from S3. Default is the Gen3 Awshelper image. - custom_image: # -- (bool) Whether to sync data from dbGaP. syncFromDbgap: false # -- (bool) Force attempting a dbgap sync if "true", falls back on user.yaml @@ -156,22 +115,10 @@ fence: guppy: # -- (bool) Whether to deploy the guppy subchart. enabled: false - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the guppy service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: hatchery: # -- (bool) Whether to deploy the hatchery subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the hatchery service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: hatchery: sidecarContainer: @@ -185,8 +132,6 @@ hatchery: env: NAMESPACE: "{{ .Release.Namespace }}" HOSTNAME: "{{ .Values.global.hostname }}" - # -- (list) Arguments to pass to the sidecare container. - args: [] # -- (list) Commands to run for the sidecar container. command: - "/bin/bash" @@ -239,12 +184,6 @@ hatchery: indexd: # -- (bool) Whether to deploy the indexd subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the indexd service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: # -- (string) the default prefix for indexd records defaultPrefix: "PREFIX/" @@ -252,96 +191,35 @@ indexd: manifestservice: # -- (bool) Whether to deploy the manifest service subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the manifest service service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: metadata: # -- (bool) Whether to deploy the metadata subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the metadata service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: peregrine: # -- (bool) Whether to deploy the peregrine subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the peregrine service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: pidgin: # -- (bool) Whether to deploy the pidgin subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the pidgin service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: portal: # -- (bool) Whether to deploy the portal subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the portal service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: - # -- (map) GitOps configuration for portal -gitops: - # -- (string) multiline string - gitops.json - json: - # -- (string) - favicon in base64 - favicon: - # -- (string) - multiline string - gitops.css - css: - # -- (string) - logo in base64 - logo: - # -- (string) - createdby.png - base64 - createdby: - sponsors: requestor: # -- (bool) Whether to deploy the requestor subchart. enabled: false - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the requestor service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: revproxy: # -- (bool) Whether to deploy the revproxy subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the revproxy service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: ingress: # -- (bool) Whether to create the custom revproxy ingress enabled: false - # -- (string) The ingress class name. - className: "" - # -- (map) Annotations to add to the ingress. - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" # -- (list) Where to route the traffic. hosts: - host: chart-example.local @@ -351,33 +229,14 @@ revproxy: sheepdog: # -- (bool) Whether to deploy the sheepdog subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the sheepdog service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: ssjdispatcher: # -- (bool) Whether to deploy the ssjdispatcher subchart. enabled: false - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the ssjdispatcher service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: - wts: # -- (bool) Whether to deploy the wts subchart. enabled: true - # -- (map) Docker image information. - image: - # -- (string) The Docker image repository for the wts service. - repository: - # -- (string) Overrides the image tag whose default is the chart appVersion. - tag: # Disable persistence by default so we can spin up and down ephemeral environments postgresql: @@ -391,7 +250,4 @@ elasticsearch: maxUnavailable: 0 singleNode: true replicas: 1 - clusterHealthCheckParams: "wait_for_status=yellow&timeout=1s" - esConfig: - elasticsearch.yml: | - # Here we can add elasticsearch config + clusterHealthCheckParams: "wait_for_status=yellow&timeout=1s" \ No newline at end of file From 9bbdc9b0d33c29912c64092aaf3dda6eb719ab13 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 7 Mar 2024 08:46:05 -0700 Subject: [PATCH 54/60] adding back empty values --- .secrets.baseline | 4 ++-- helm/gen3/README.md | 5 +++++ helm/gen3/values.yaml | 12 ++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 02c4f488..080394ac 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2024-03-07T15:30:30Z", + "generated_at": "2024-03-07T15:45:14Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -330,7 +330,7 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 164, + "line_number": 172, "type": "Secret Keyword" } ], diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 36814cfc..2072cf58 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -53,6 +53,9 @@ Helm chart to deploy Gen3 Data Commons | audit.enabled | bool | `true` | Whether to deploy the audit subchart. | | aws-es-proxy.enabled | bool | `false` | Whether to deploy the aws-es-proxy subchart. | | aws-es-proxy.esEndpoint | str | `"test.us-east-1.es.amazonaws.com"` | Elasticsearch endpoint in AWS | +| aws-es-proxy.secrets | map | `{"awsAccessKeyId":"","awsSecretAccessKey":""}` | Secret information | +| aws-es-proxy.secrets.awsAccessKeyId | str | `""` | AWS access key ID for aws-es-proxy | +| aws-es-proxy.secrets.awsSecretAccessKey | str | `""` | AWS secret access key for aws-es-proxy | | elasticsearch.clusterHealthCheckParams | string | `"wait_for_status=yellow&timeout=1s"` | | | elasticsearch.clusterName | string | `"gen3-elasticsearch"` | | | elasticsearch.maxUnavailable | int | `0` | | @@ -120,6 +123,7 @@ Helm chart to deploy Gen3 Data Commons | hatchery.hatchery.containers[0].use-tls | string | `"false"` | | | hatchery.hatchery.containers[0].user-uid | int | `1000` | | | hatchery.hatchery.containers[0].user-volume-location | string | `"/home/jovyan/pd"` | | +| hatchery.hatchery.sidecarContainer.args | list | `[]` | Arguments to pass to the sidecare container. | | hatchery.hatchery.sidecarContainer.command | list | `["/bin/bash","./sidecar.sh"]` | Commands to run for the sidecar container. | | hatchery.hatchery.sidecarContainer.cpu-limit | string | `"0.1"` | The maximum amount of CPU the sidecar container can use | | hatchery.hatchery.sidecarContainer.env | map | `{"HOSTNAME":"{{ .Values.global.hostname }}","NAMESPACE":"{{ .Release.Namespace }}"}` | Environment variables to pass to the sidecar container | @@ -141,6 +145,7 @@ Helm chart to deploy Gen3 Data Commons | postgresql.primary.persistence.enabled | bool | `false` | Option to persist the dbs data. | | requestor.enabled | bool | `false` | Whether to deploy the requestor subchart. | | revproxy.enabled | bool | `true` | Whether to deploy the revproxy subchart. | +| revproxy.ingress.annotations | map | `{}` | Annotations to add to the ingress. | | revproxy.ingress.enabled | bool | `false` | Whether to create the custom revproxy ingress | | revproxy.ingress.hosts | list | `[{"host":"chart-example.local"}]` | Where to route the traffic. | | revproxy.ingress.tls | list | `[]` | To secure an Ingress by specifying a secret that contains a TLS private key and certificate. | diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index 79eeb0a6..a8aaaf7c 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -85,6 +85,12 @@ aws-es-proxy: enabled: false # -- (str) Elasticsearch endpoint in AWS esEndpoint: test.us-east-1.es.amazonaws.com + # -- (map) Secret information + secrets: + # -- (str) AWS access key ID for aws-es-proxy + awsAccessKeyId: "" + # -- (str) AWS secret access key for aws-es-proxy + awsSecretAccessKey: "" etl: # -- (bool) Whether to deploy the etl subchart. @@ -132,6 +138,8 @@ hatchery: env: NAMESPACE: "{{ .Release.Namespace }}" HOSTNAME: "{{ .Values.global.hostname }}" + # -- (list) Arguments to pass to the sidecare container. + args: [] # -- (list) Commands to run for the sidecar container. command: - "/bin/bash" @@ -220,6 +228,10 @@ revproxy: ingress: # -- (bool) Whether to create the custom revproxy ingress enabled: false + # -- (map) Annotations to add to the ingress. + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" # -- (list) Where to route the traffic. hosts: - host: chart-example.local From 9a065796660ea97680591f8f0c883421f2900b22 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 7 Mar 2024 13:09:33 -0700 Subject: [PATCH 55/60] adding logic to allow users to run external secrets and the dbcreate job for testing purposes --- .secrets.baseline | 4 ++-- docs/external_secrets.md | 2 ++ helm/common/templates/_db_setup_job.tpl | 2 ++ helm/gen3/README.md | 3 ++- helm/gen3/values.yaml | 2 ++ 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 080394ac..f73a9b75 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2024-03-07T15:45:14Z", + "generated_at": "2024-03-07T20:08:55Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -330,7 +330,7 @@ "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 172, + "line_number": 174, "type": "Secret Keyword" } ], diff --git a/docs/external_secrets.md b/docs/external_secrets.md index a93353c1..ac507fb9 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -89,6 +89,8 @@ For users requiring a more selective application of external secrets — targeti External secret resources will only attempt to replace Kubernetes secrets when a corresponding secret is successfully located within the Secrets Manager. In instances where a specific secret is not found, the External Secrets resource will indicate a `SecretSyncedError`, signaling the absence of the targeted resource within the Secrets Manager. This error is acceptable and helpful for users who want to enable the use of AWS Secrets Manager for some, but not all the secrets in a specific Helm chart. +However, if you wish to utilize External Secrets for managing non-database secrets while still automating the creation of your database secrets, you can configure this behavior explicitly. Set `.Values.global.externalSecrets.dbCreate` to true alongside `.Values.global.postgres.dbCreate` or `.Values.postgres.dbCreate` to initiate the database creation job. This configuration will result in the creation of the necessary databases with their credentials stored securely within Kubernetes Secrets. Subsequently, you also choose to create Secrets in Secrets manager with the values that were generated from teh dbCreate job if you wish to store these credentials long term. + #### Independent Subchart Deployment In scenarios where subcharts are deployed independently, outside the scope of the umbrella chart, it is crucial to set the `.Values.global.externalSecrets.deploy` directive within the `values.yaml` file for each specific service. diff --git a/helm/common/templates/_db_setup_job.tpl b/helm/common/templates/_db_setup_job.tpl index af90d9e8..e63bea0f 100644 --- a/helm/common/templates/_db_setup_job.tpl +++ b/helm/common/templates/_db_setup_job.tpl @@ -169,6 +169,7 @@ spec: Create k8s secrets for connecting to postgres */}} # DB Secrets +{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.global.externalSecrets.dbCreate) }} {{- define "common.db-secret" -}} apiVersion: v1 kind: Secret @@ -184,4 +185,5 @@ data: {{- else }} host: {{ ( $.Values.postgres.host | default ( $.Values.global.postgres.master.host)) | b64enc | quote }} {{- end }} +{{- end }} {{- end }} \ No newline at end of file diff --git a/helm/gen3/README.md b/helm/gen3/README.md index 2072cf58..50b8b7cd 100644 --- a/helm/gen3/README.md +++ b/helm/gen3/README.md @@ -84,7 +84,8 @@ Helm chart to deploy Gen3 Data Commons | global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | URL of the data dictionary. | | global.dispatcherJobNum | int | `"10"` | Number of dispatcher jobs. | | global.environment | string | `"default"` | Environment name. This should be the same as vpcname if you're doing an AWS deployment. Currently this is being used to share ALB's if you have multiple namespaces in same cluster. | -| global.externalSecrets | map | `{"deploy":false}` | External Secrets settings. | +| global.externalSecrets | map | `{"dbCreate":false,"deploy":false}` | External Secrets settings. | +| global.externalSecrets.dbCreate | bool | `false` | Will create the databases and store the creds in Kubernetes Secrets even if externalSecrets is deployed. Useful if you want to use ExternalSecrets for other secrets besides db secrets. | | global.externalSecrets.deploy | bool | `false` | Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override secrets you have deployed. | | global.hostname | string | `"localhost"` | Hostname for the deployment. | | global.netPolicy | bool | `true` | Whether network policies are enabled. | diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index a8aaaf7c..e8878115 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -60,6 +60,8 @@ global: externalSecrets: # -- (bool) Will use ExternalSecret resources to pull secrets from Secrets Manager instead of creating them locally. Be cautious as this will override secrets you have deployed. deploy: false + # -- (bool) Will create the databases and store the creds in Kubernetes Secrets even if externalSecrets is deployed. Useful if you want to use ExternalSecrets for other secrets besides db secrets. + dbCreate: false # Dependancy Charts From 28ad27fc66ed6bbbb587d8c708dbdacc90b88c81 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 7 Mar 2024 13:35:43 -0700 Subject: [PATCH 56/60] fixing the location of the define command for db secrets --- helm/common/templates/_db_setup_job.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/common/templates/_db_setup_job.tpl b/helm/common/templates/_db_setup_job.tpl index e63bea0f..9ea67dbe 100644 --- a/helm/common/templates/_db_setup_job.tpl +++ b/helm/common/templates/_db_setup_job.tpl @@ -169,8 +169,8 @@ spec: Create k8s secrets for connecting to postgres */}} # DB Secrets -{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.global.externalSecrets.dbCreate) }} {{- define "common.db-secret" -}} +{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.global.externalSecrets.dbCreate) }} apiVersion: v1 kind: Secret metadata: From 2fdb1ec1841ace324a3a4f5ce01221afd638d3e2 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 7 Mar 2024 13:51:12 -0700 Subject: [PATCH 57/60] fixing the new line at the end of the values.yaml file --- helm/gen3/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index e8878115..b29b75f1 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -264,4 +264,4 @@ elasticsearch: maxUnavailable: 0 singleNode: true replicas: 1 - clusterHealthCheckParams: "wait_for_status=yellow&timeout=1s" \ No newline at end of file + clusterHealthCheckParams: "wait_for_status=yellow&timeout=1s" From 05d8700f133c115587ae804f4dac62bedfe8251d Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 7 Mar 2024 14:21:34 -0700 Subject: [PATCH 58/60] changing userysnc to use a role and rolebinding instead of a cluster role and cluster rolebinding --- helm/fence/templates/usersync-sa.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helm/fence/templates/usersync-sa.yaml b/helm/fence/templates/usersync-sa.yaml index 379271ce..f86ff821 100644 --- a/helm/fence/templates/usersync-sa.yaml +++ b/helm/fence/templates/usersync-sa.yaml @@ -5,7 +5,7 @@ metadata: name: usersync-job --- apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole +kind: Role metadata: name: usersync-job-role rules: @@ -14,12 +14,12 @@ rules: verbs: ["get", "list", "watch", "create", "update", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding +kind: RoleBinding metadata: name: usersync-job-role-binding roleRef: apiGroup: rbac.authorization.k8s.io - kind: ClusterRole + kind: Role name: usersync-job-role subjects: - kind: ServiceAccount From 116098745d0e551872f33446e935c404a9639c10 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Thu, 7 Mar 2024 16:11:34 -0700 Subject: [PATCH 59/60] changing the default aws ingres security policy --- helm/revproxy/templates/ingress_aws.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/revproxy/templates/ingress_aws.yaml b/helm/revproxy/templates/ingress_aws.yaml index 530e276b..cd0f1da7 100644 --- a/helm/revproxy/templates/ingress_aws.yaml +++ b/helm/revproxy/templates/ingress_aws.yaml @@ -10,7 +10,7 @@ metadata: alb.ingress.kubernetes.io/group.name: {{ .Values.global.environment }} alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' - alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06 + alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-Res-FIPS-2023-04 spec: ingressClassName: alb rules: From 1e3d7e1324fa55bf00f986d5f20c8e7f0b4054e5 Mon Sep 17 00:00:00 2001 From: EliseCastle23 Date: Mon, 11 Mar 2024 12:39:28 -0600 Subject: [PATCH 60/60] adding ability to conditionally include native helm secret creation with External Secrets. Also, adding the metadata-g3auto secret to External Secrets. Updating documentation and fixing small syntax error. --- .secrets.baseline | 14 ++++----- docs/external_secrets.md | 20 +++++++++++- helm/audit/README.md | 3 +- helm/audit/templates/secrets.yaml | 4 ++- helm/audit/values.yaml | 2 ++ helm/fence/README.md | 3 +- helm/fence/templates/fence-config.yaml | 4 ++- helm/fence/templates/fence-secret.yaml | 2 ++ helm/fence/templates/jwt-keys.yaml | 2 ++ helm/fence/values.yaml | 2 ++ helm/indexd/README.md | 3 +- helm/indexd/templates/indexd-secret.yaml | 4 ++- helm/indexd/values.yaml | 2 ++ helm/manifestservice/README.md | 3 +- .../templates/manifestservice-creds.yaml | 2 ++ helm/manifestservice/values.yaml | 2 ++ helm/metadata/README.md | 4 ++- helm/metadata/templates/_helpers.tpl | 7 +++++ helm/metadata/templates/external-secret.yaml | 31 +++++++++++++++++++ helm/metadata/templates/secrets.yaml | 4 ++- helm/metadata/values.yaml | 4 +++ 21 files changed, 105 insertions(+), 17 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index f73a9b75..97cb04f0 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2024-03-07T20:08:55Z", + "generated_at": "2024-03-11T18:38:21Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -220,28 +220,28 @@ "hashed_secret": "b266a6d0f00bb36f6b98134bf4cec71f2d7943a3", "is_secret": false, "is_verified": false, - "line_number": 99, + "line_number": 100, "type": "Secret Keyword" }, { "hashed_secret": "d84ce25b0f9bc2cc263006ae39453efb22cc2900", "is_secret": false, "is_verified": false, - "line_number": 124, + "line_number": 125, "type": "Secret Keyword" }, { "hashed_secret": "f09dd6e359833a12f48c4c4255d6e87a6e55cfe9", "is_secret": false, "is_verified": false, - "line_number": 151, + "line_number": 152, "type": "Secret Keyword" }, { "hashed_secret": "9d8fada0e01336e865c461bb3549084d206fe6da", "is_secret": false, "is_verified": false, - "line_number": 197, + "line_number": 198, "type": "Secret Keyword" } ], @@ -305,7 +305,7 @@ "hashed_secret": "5d07e1b80e448a213b392049888111e1779a52db", "is_secret": false, "is_verified": false, - "line_number": 1955, + "line_number": 1957, "type": "Secret Keyword" } ], @@ -414,7 +414,7 @@ "hashed_secret": "d2e2ab0f407e4ee3cf2ab87d61c31b25a74085e5", "is_secret": false, "is_verified": false, - "line_number": 12, + "line_number": 13, "type": "Secret Keyword" } ], diff --git a/docs/external_secrets.md b/docs/external_secrets.md index ac507fb9..cf4dd5ca 100644 --- a/docs/external_secrets.md +++ b/docs/external_secrets.md @@ -89,7 +89,25 @@ For users requiring a more selective application of external secrets — targeti External secret resources will only attempt to replace Kubernetes secrets when a corresponding secret is successfully located within the Secrets Manager. In instances where a specific secret is not found, the External Secrets resource will indicate a `SecretSyncedError`, signaling the absence of the targeted resource within the Secrets Manager. This error is acceptable and helpful for users who want to enable the use of AWS Secrets Manager for some, but not all the secrets in a specific Helm chart. -However, if you wish to utilize External Secrets for managing non-database secrets while still automating the creation of your database secrets, you can configure this behavior explicitly. Set `.Values.global.externalSecrets.dbCreate` to true alongside `.Values.global.postgres.dbCreate` or `.Values.postgres.dbCreate` to initiate the database creation job. This configuration will result in the creation of the necessary databases with their credentials stored securely within Kubernetes Secrets. Subsequently, you also choose to create Secrets in Secrets manager with the values that were generated from teh dbCreate job if you wish to store these credentials long term. +However, if you wish to utilize External Secrets for managing non-database secrets while still automating the creation of your database secrets, you can configure this behavior explicitly. Set `.Values.global.externalSecrets.dbCreate` to true alongside `.Values.global.postgres.dbCreate` or `.Values.postgres.dbCreate` to initiate the database creation job. This configuration will result in the creation of the necessary databases with their credentials stored securely within Kubernetes Secrets. Subsequently, you also choose to create Secrets in Secrets manager with the values that were generated from the dbCreate job if you wish to store these credentials long term. + +By default, the following services will not create the Helm internal secrets when Secrets Manager is enabled: +- Audit +- Fence +- Indexd +- Manifestservice +- Metadata + +This is because CD tools like Argocd will have trouble syncing resources if the K8s secret was generated via Helm and External Secrets continues to override it. You can configure Helm to still create these secrets with External Secrets enabled by setting the appropriate variable to true. + +For example, to ensure the "audit-g3auto" secret is still created by Helm, you would need to set the following in your values.yaml file: +``` +audit: + # -- (map) External Secrets settings. + externalSecrets: + # -- (string) Will create the Helm "audit-g3auto" secret even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. + createK8sAuditSecret: true +``` #### Independent Subchart Deployment In scenarios where subcharts are deployed independently, outside the scope of the umbrella chart, it is crucial to set the `.Values.global.externalSecrets.deploy` directive within the `values.yaml` file for each specific service. diff --git a/helm/audit/README.md b/helm/audit/README.md index 03ff4421..96172b65 100644 --- a/helm/audit/README.md +++ b/helm/audit/README.md @@ -36,8 +36,9 @@ A Helm chart for Kubernetes | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"DEBUG","value":"false"},{"name":"ARBORIST_URL","valueFrom":{"configMapKeyRef":{"key":"arborist_url","name":"manifest-global","optional":true}}}]` | Environment variables to pass to the container | -| externalSecrets | map | `{"auditG3auto":null,"dbcreds":null}` | External Secrets settings. | +| externalSecrets | map | `{"auditG3auto":null,"createK8sAuditSecret":false,"dbcreds":null}` | External Secrets settings. | | externalSecrets.auditG3auto | string | `nil` | Will override the name of the aws secrets manager secret. Default is "audit-g3auto" | +| externalSecrets.createK8sAuditSecret | string | `false` | Will create the Helm "audit-g3auto" secret even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. | | externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the chart, which is used as the name of resources created by the chart | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | diff --git a/helm/audit/templates/secrets.yaml b/helm/audit/templates/secrets.yaml index 03a39c51..b1073381 100644 --- a/helm/audit/templates/secrets.yaml +++ b/helm/audit/templates/secrets.yaml @@ -1,3 +1,4 @@ +{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.externalSecrets.createK8sAuditSecret) }} apiVersion: v1 kind: Secret metadata: @@ -49,4 +50,5 @@ stringData: # whether to return usernames in query responses, # and to allow querying by username - QUERY_USERNAMES: true \ No newline at end of file + QUERY_USERNAMES: true +{{- end }} \ No newline at end of file diff --git a/helm/audit/values.yaml b/helm/audit/values.yaml index fe38164c..0112fb8a 100644 --- a/helm/audit/values.yaml +++ b/helm/audit/values.yaml @@ -67,6 +67,8 @@ global: # -- (map) External Secrets settings. externalSecrets: + # -- (string) Will create the Helm "audit-g3auto" secret even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. + createK8sAuditSecret: false # -- (string) Will override the name of the aws secrets manager secret. Default is "audit-g3auto" auditG3auto: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" diff --git a/helm/fence/README.md b/helm/fence/README.md index d4a3ef33..7179e211 100644 --- a/helm/fence/README.md +++ b/helm/fence/README.md @@ -89,7 +89,8 @@ A Helm chart for gen3 Fence | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"GEN3_UWSGI_TIMEOUT","valueFrom":{"configMapKeyRef":{"key":"uwsgi-timeout","name":"manifest-global","optional":true}}},{"name":"DD_AGENT_HOST","valueFrom":{"fieldRef":{"fieldPath":"status.hostIP"}}},{"name":"AWS_STS_REGIONAL_ENDPOINTS","value":"regional"},{"name":"PYTHONPATH","value":"/var/www/fence"},{"name":"GEN3_DEBUG","value":"False"},{"name":"FENCE_PUBLIC_CONFIG","valueFrom":{"configMapKeyRef":{"key":"fence-config-public.yaml","name":"manifest-fence","optional":true}}},{"name":"PGHOST","valueFrom":{"secretKeyRef":{"key":"host","name":"fence-dbcreds","optional":false}}},{"name":"PGUSER","valueFrom":{"secretKeyRef":{"key":"username","name":"fence-dbcreds","optional":false}}},{"name":"PGPASSWORD","valueFrom":{"secretKeyRef":{"key":"password","name":"fence-dbcreds","optional":false}}},{"name":"PGDB","valueFrom":{"secretKeyRef":{"key":"database","name":"fence-dbcreds","optional":false}}},{"name":"DBREADY","valueFrom":{"secretKeyRef":{"key":"dbcreated","name":"fence-dbcreds","optional":false}}},{"name":"DB","value":"postgresql://$(PGUSER):$(PGPASSWORD)@$(PGHOST):5432/$(PGDB)"},{"name":"INDEXD_PASSWORD","valueFrom":{"secretKeyRef":{"key":"fence","name":"indexd-service-creds"}}},{"name":"gen3Env","valueFrom":{"configMapKeyRef":{"key":"hostname","name":"manifest-global"}}}]` | Environment variables to pass to the container | -| externalSecrets | map | `{"dbcreds":null,"fenceConfig":null,"fenceGoogleAppCredsSecret":null,"fenceGoogleStorageCredsSecret":null,"fenceJwtKeys":null}` | External Secrets settings. | +| externalSecrets | map | `{"createK8sFenceSecrets":false,"dbcreds":null,"fenceConfig":null,"fenceGoogleAppCredsSecret":null,"fenceGoogleStorageCredsSecret":null,"fenceJwtKeys":null}` | External Secrets settings. | +| externalSecrets.createK8sFenceSecrets | string | `false` | Will create the Helm "fence-config", "fence-google-app-creds-secret", "fence-google-storage-creds-secret", and "fence-jwt-keys" secrets even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. | | externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | externalSecrets.fenceConfig | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-config" | | externalSecrets.fenceGoogleAppCredsSecret | string | `nil` | Will override the name of the aws secrets manager secret. Default is "fence-google-app-creds-secret" | diff --git a/helm/fence/templates/fence-config.yaml b/helm/fence/templates/fence-config.yaml index 29d0df2e..cd7943d9 100644 --- a/helm/fence/templates/fence-config.yaml +++ b/helm/fence/templates/fence-config.yaml @@ -1,3 +1,4 @@ +{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.externalSecrets.createK8sFenceSecrets) }} apiVersion: v1 kind: Secret metadata: @@ -8,4 +9,5 @@ stringData: {{- with .Values.FENCE_CONFIG }} {{- toYaml . | nindent 4 }} {{ end }} ---- \ No newline at end of file +--- +{{- end }} diff --git a/helm/fence/templates/fence-secret.yaml b/helm/fence/templates/fence-secret.yaml index 6ac60bde..0c1e0832 100644 --- a/helm/fence/templates/fence-secret.yaml +++ b/helm/fence/templates/fence-secret.yaml @@ -1,3 +1,4 @@ +{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.externalSecrets.createK8sFenceSecrets) }} apiVersion: v1 kind: Secret metadata: @@ -21,3 +22,4 @@ metadata: type: Opaque data: {{ (.Files.Glob "fence-google-creds/*").AsSecrets | indent 2 }} +{{- end }} \ No newline at end of file diff --git a/helm/fence/templates/jwt-keys.yaml b/helm/fence/templates/jwt-keys.yaml index 893a4488..68d72895 100644 --- a/helm/fence/templates/jwt-keys.yaml +++ b/helm/fence/templates/jwt-keys.yaml @@ -1,3 +1,4 @@ +{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.externalSecrets.createK8sFenceSecrets) }} apiVersion: v1 kind: Secret metadata: @@ -5,3 +6,4 @@ metadata: type: Opaque data: jwt_private_key.pem: {{ include "getOrCreatePrivateKey" . }} +{{- end }} \ No newline at end of file diff --git a/helm/fence/values.yaml b/helm/fence/values.yaml index 2e611279..973bb815 100644 --- a/helm/fence/values.yaml +++ b/helm/fence/values.yaml @@ -80,6 +80,8 @@ global: # -- (map) External Secrets settings. externalSecrets: + # -- (string) Will create the Helm "fence-config", "fence-google-app-creds-secret", "fence-google-storage-creds-secret", and "fence-jwt-keys" secrets even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. + createK8sFenceSecrets: false # -- (string) Will override the name of the aws secrets manager secret. Default is "fence-jwt-keys" fenceJwtKeys: # -- (string) Will override the name of the aws secrets manager secret. Default is "fence-google-app-creds-secret" diff --git a/helm/indexd/README.md b/helm/indexd/README.md index 4f07b6ab..55098555 100644 --- a/helm/indexd/README.md +++ b/helm/indexd/README.md @@ -27,7 +27,8 @@ A Helm chart for gen3 indexd | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | defaultPrefix | string | `"PREFIX/"` | default prefix for indexd | | env | list | `[{"name":"ARBORIST","value":"true"},{"name":"GEN3_DEBUG","value":"False"}]` | Environment variables to pass to the container | -| externalSecrets | map | `{"dbcreds":null,"serviceCreds":"indexd-service-creds"}` | External Secrets settings. | +| externalSecrets | map | `{"createK8sServiceCredsSecret":false,"dbcreds":null,"serviceCreds":"indexd-service-creds"}` | External Secrets settings. | +| externalSecrets.createK8sServiceCredsSecret | string | `false` | Will create the Helm "indexd-service-creds" secret even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. | | externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | | fullnameOverride | string | `""` | Override the full name of the deployment. | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | diff --git a/helm/indexd/templates/indexd-secret.yaml b/helm/indexd/templates/indexd-secret.yaml index 12ab5364..d9fb1864 100644 --- a/helm/indexd/templates/indexd-secret.yaml +++ b/helm/indexd/templates/indexd-secret.yaml @@ -1,3 +1,4 @@ +{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.externalSecrets.createK8sServiceCredsSecret) }} apiVersion: v1 kind: Secret metadata: @@ -13,4 +14,5 @@ metadata: type: Opaque data: fence: {{ include "common.getOrGenSecret" (list .Values.secrets.userdb.fence "indexd-service-creds" "fence" 20 .Release.Namespace) }} - sheepdog: {{ include "common.getOrGenSecret" (list .Values.secrets.userdb.sheepdog "indexd-service-creds" "sheepdog" 20 .Release.Namespace) }} \ No newline at end of file + sheepdog: {{ include "common.getOrGenSecret" (list .Values.secrets.userdb.sheepdog "indexd-service-creds" "sheepdog" 20 .Release.Namespace) }} +{{- end }} \ No newline at end of file diff --git a/helm/indexd/values.yaml b/helm/indexd/values.yaml index 6d2bd52f..8c64335d 100644 --- a/helm/indexd/values.yaml +++ b/helm/indexd/values.yaml @@ -70,6 +70,8 @@ global: # -- (map) External Secrets settings. externalSecrets: + # -- (string) Will create the Helm "indexd-service-creds" secret even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. + createK8sServiceCredsSecret: false # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" dbcreds: serviceCreds: "indexd-service-creds" diff --git a/helm/manifestservice/README.md b/helm/manifestservice/README.md index 7f120f2d..a854343d 100644 --- a/helm/manifestservice/README.md +++ b/helm/manifestservice/README.md @@ -33,7 +33,8 @@ A Helm chart for Kubernetes | datadogProfilingEnabled | bool | `true` | If enabled, the Datadog Agent will collect profiling data for your application using the Continuous Profiler. This data can be used to identify performance bottlenecks and optimize your application. | | datadogTraceSampleRate | int | `1` | A value between 0 and 1, that represents the percentage of requests that will be traced. For example, a value of 0.5 means that 50% of requests will be traced. | | env | list | `[{"name":"REQUESTS_CA_BUNDLE","value":"/etc/ssl/certs/ca-certificates.crt"},{"name":"MANIFEST_SERVICE_CONFIG_PATH","value":"/var/gen3/config/config.json"},{"name":"GEN3_DEBUG","value":"False"}]` | Environment variables to pass to the container | -| externalSecrets | map | `{"manifestserviceG3auto":null}` | External Secrets settings. | +| externalSecrets | map | `{"createK8sManifestServiceSecret":false,"manifestserviceG3auto":null}` | External Secrets settings. | +| externalSecrets.createK8sManifestServiceSecret | string | `false` | Will create the Helm "manifestservice-g3auto" secret even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. | | externalSecrets.manifestserviceG3auto | string | `nil` | Will override the name of the aws secrets manager secret. Default is "manifestservice-g3auto" | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | diff --git a/helm/manifestservice/templates/manifestservice-creds.yaml b/helm/manifestservice/templates/manifestservice-creds.yaml index 5194515c..c1aedb9a 100644 --- a/helm/manifestservice/templates/manifestservice-creds.yaml +++ b/helm/manifestservice/templates/manifestservice-creds.yaml @@ -1,3 +1,4 @@ +{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.externalSecrets.createK8sManifestServiceSecret) }} apiVersion: v1 kind: Secret metadata: @@ -12,3 +13,4 @@ stringData: "aws_secret_access_key": "{{ .Values.manifestserviceG3auto.awssecretkey }}", "prefix": "{{ .Values.manifestserviceG3auto.prefix }}" } +{{- end }} \ No newline at end of file diff --git a/helm/manifestservice/values.yaml b/helm/manifestservice/values.yaml index f4c1a2bd..09cd04f3 100644 --- a/helm/manifestservice/values.yaml +++ b/helm/manifestservice/values.yaml @@ -30,6 +30,8 @@ global: # -- (map) External Secrets settings. externalSecrets: + # -- (string) Will create the Helm "manifestservice-g3auto" secret even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. + createK8sManifestServiceSecret: false # -- (string) Will override the name of the aws secrets manager secret. Default is "manifestservice-g3auto" manifestserviceG3auto: # -- (map) Secret information for External Secrets. diff --git a/helm/metadata/README.md b/helm/metadata/README.md index d823f844..d533375e 100644 --- a/helm/metadata/README.md +++ b/helm/metadata/README.md @@ -46,8 +46,10 @@ A Helm chart for gen3 Metadata Service | elasticsearch.separate | bool | `false` | | | elasticsearch.singleNode | bool | `true` | | | esEndpoint | string | `"http://gen3-elasticsearch-master:9200"` | Elasticsearch endpoint. | -| externalSecrets | map | `{"dbcreds":null}` | External Secrets settings. | +| externalSecrets | map | `{"createK8sMetadataSecret":false,"dbcreds":null,"metadataG3auto":null}` | External Secrets settings. | +| externalSecrets.createK8sMetadataSecret | string | `false` | Will create the Helm "metadata-g3auto" secret even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. | | externalSecrets.dbcreds | string | `nil` | Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" | +| externalSecrets.metadataG3auto | string | `nil` | Will override the name of the aws secrets manager secret. Default is "metadata-g3auto" | | global.aws | map | `{"awsAccessKeyId":null,"awsSecretAccessKey":null,"enabled":false}` | AWS configuration | | global.aws.awsAccessKeyId | string | `nil` | Credentials for AWS stuff. | | global.aws.awsSecretAccessKey | string | `nil` | Credentials for AWS stuff. | diff --git a/helm/metadata/templates/_helpers.tpl b/helm/metadata/templates/_helpers.tpl index f8424983..91c790fd 100644 --- a/helm/metadata/templates/_helpers.tpl +++ b/helm/metadata/templates/_helpers.tpl @@ -77,3 +77,10 @@ Create the name of the service account to use {{- default .Values.postgres.password }} {{- end }} {{- end }} + +{{/* + Metadata g3 Auto Secrets Manager Name +*/}} +{{- define "metadata-g3auto" -}} +{{- default "metadata-g3auto" .Values.externalSecrets.metadataG3auto }} +{{- end }} \ No newline at end of file diff --git a/helm/metadata/templates/external-secret.yaml b/helm/metadata/templates/external-secret.yaml index 70c278fe..c3bb3465 100644 --- a/helm/metadata/templates/external-secret.yaml +++ b/helm/metadata/templates/external-secret.yaml @@ -1 +1,32 @@ +{{ if .Values.global.externalSecrets.deploy }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: metadata-g3auto +spec: + refreshInterval: 5m + secretStoreRef: + name: {{include "common.SecretStore" .}} + kind: SecretStore + target: + name: metadata-g3auto + creationPolicy: Owner + data: + - secretKey: base64Authz.txt + remoteRef: + #name of secret in secrets manager + key: {{include "metadata-g3auto" .}} + property: base64Authz.txt + - secretKey: dbcreds.json + remoteRef: + #name of secret in secrets manager + key: {{include "metadata-g3auto" .}} + property: dbcreds.json + - secretKey: metadata.env + remoteRef: + #name of secret in secrets manager + key: {{include "metadata-g3auto" .}} + property: metadata.env +{{- end }} +--- {{ include "common.externalSecret.db" . }} \ No newline at end of file diff --git a/helm/metadata/templates/secrets.yaml b/helm/metadata/templates/secrets.yaml index fcde0e48..d9e22e27 100644 --- a/helm/metadata/templates/secrets.yaml +++ b/helm/metadata/templates/secrets.yaml @@ -1,3 +1,4 @@ +{{- if or (not .Values.global.externalSecrets.deploy) (and .Values.global.externalSecrets.deploy .Values.externalSecrets.createK8sMetadataSecret) }} apiVersion: v1 kind: Secret metadata: @@ -18,4 +19,5 @@ stringData: DB_USER={{ .Values.postgres.user }} DB_PASSWORD={{ include "metadata.postgres.password" . }} DB_DATABASE={{ .Values.postgres.dbname }} - ADMIN_LOGINS={{ $randomPass }} \ No newline at end of file + ADMIN_LOGINS={{ $randomPass }} +{{- end }} \ No newline at end of file diff --git a/helm/metadata/values.yaml b/helm/metadata/values.yaml index 84b26e0a..d3953808 100644 --- a/helm/metadata/values.yaml +++ b/helm/metadata/values.yaml @@ -68,6 +68,10 @@ global: # -- (map) External Secrets settings. externalSecrets: + # -- (string) Will create the Helm "metadata-g3auto" secret even if Secrets Manager is enabled. This is helpful if you are wanting to use External Secrets for some, but not all secrets. + createK8sMetadataSecret: false + # -- (string) Will override the name of the aws secrets manager secret. Default is "metadata-g3auto" + metadataG3auto: # -- (string) Will override the name of the aws secrets manager secret. Default is "Values.global.environment-.Chart.Name-creds" dbcreds: # -- (map) Secret information to access the db restore job S3 bucket.