From 399370f0d222157ca5ea00819a556af8de218afe Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 25 Mar 2024 16:07:58 +0100 Subject: [PATCH 001/222] Bind mount /etc/pki in the wrapper This is useful whenever a custom CA is installed on the system and is needed to connect to a remote cluster. --- scripts/pattern-util.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 9cec19fa..ea02b7ef 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -56,6 +56,7 @@ podman run -it --rm --pull=newer \ --security-opt label=disable \ -e EXTRA_HELM_OPTS \ -e KUBECONFIG \ + -v /etc/pki:/etc/pki:ro \ -v "${HOME}":"${HOME}" \ -v "${HOME}":/pattern-home \ ${PODMAN_ARGS} \ From a88f040f1a0a4880ed90b1adf3ffec8ea57b6d6b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 25 Mar 2024 17:27:09 +0100 Subject: [PATCH 002/222] Properly error out in preview-all when we cannot connect to the cluster Before: $ ./pattern.sh make preview-all make -f common/Makefile preview-all make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' error: Missing or incomplete configuration info. Please point to an existing, complete config file: 1. Via the command-line flag --kubeconfig 2. Via the KUBECONFIG environment variable 3. In your home directory as ~/.kube/config To view or setup config directly use the 'config' command. error: Missing or incomplete configuration info. Please point to an existing, complete config file: 1. Via the command-line flag --kubeconfig 2. Via the KUBECONFIG environment variable 3. In your home directory as ~/.kube/config To view or setup config directly use the 'config' command. ...This goes on for many more iterations... After: $ ./pattern.sh make preview-all make -f common/Makefile preview-all make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Could not access the cluster: error: Missing or incomplete configuration info. Please point to an existing, complete config file: 1. Via the command-line flag --kubeconfig 2. Via the KUBECONFIG environment variable 3. In your home directory as ~/.kube/config To view or setup config directly use the 'config' command. make[1]: *** [common/Makefile:59: preview-all] Error 1 make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make: *** [Makefile:12: preview-all] Error 2 --- scripts/preview-all.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/preview-all.sh b/scripts/preview-all.sh index cc7775bf..296e7dc8 100755 --- a/scripts/preview-all.sh +++ b/scripts/preview-all.sh @@ -7,6 +7,14 @@ HUB=$( yq ".main.clusterGroupName" values-global.yaml ) MANAGED_CLUSTERS=$( yq ".clusterGroup.managedClusterGroups.[].name" values-$HUB.yaml ) ALL_CLUSTERS=( $HUB $MANAGED_CLUSTERS ) +CLUSTER_INFO_OUT=$(oc cluster-info 2>&1) +CLUSTER_INFO_RET=$? +if [ $CLUSTER_INFO_RET -ne 0 ]; then + echo "Could not access the cluster:" + echo "${CLUSTER_INFO_OUT}" + exit 1 +fi + for cluster in ${ALL_CLUSTERS[@]}; do APPS=$( yq ".clusterGroup.applications.[].name" values-$cluster.yaml ) for app in $APPS; do From ffd421b5117c0867677cc19f75aa67af6b40687e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 25 Mar 2024 17:44:32 +0100 Subject: [PATCH 003/222] Only include values files if they do exist in preview.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is because in helm we use "ignoreMissingValueFiles: true". I.e. we just ignore non existing value files. Let's do the same for the preview.sh script. Before: ❯ make preview-all make -f common/Makefile preview-all make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Error: open /home/michele/Engineering/cloud-patterns/multicloud-gitops/overrides/values-None.yaml: no such file or directory Error: open /home/michele/Engineering/cloud-patterns/multicloud-gitops/overrides/values-None.yaml: no such file or directory Error: open /home/michele/Engineering/cloud-patterns/multicloud-gitops/overrides/values-None.yaml: no such file or directory Error: open /home/michele/Engineering/cloud-patterns/multicloud-gitops/overrides/values-None.yaml: no such file or directory Error: open /home/michele/Engineering/cloud-patterns/multicloud-gitops/overrides/values-None.yaml: no such file or directory common/scripts/preview.sh: eval: line 79: unexpected EOF while looking for matching `"' common/scripts/preview.sh: eval: line 79: unexpected EOF while looking for matching `"' common/scripts/preview.sh: eval: line 79: unexpected EOF while looking for matching `"' make[1]: *** [common/Makefile:59: preview-all] Error 2 make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make: *** [Makefile:12: preview-all] Error 2 After: ❯ make preview-all > /dev/null ; echo $? 0 --- scripts/preview.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/preview.sh b/scripts/preview.sh index 379f240d..2d8079cf 100755 --- a/scripts/preview.sh +++ b/scripts/preview.sh @@ -62,16 +62,16 @@ OVERRIDES=$( getOverrides ) VALUE_FILES="" IFS=$'\n' for line in $sharedValueFiles; do - if [ $line != "null" ]; then - file=$(replaceGlobals $line) - VALUE_FILES="$VALUE_FILES -f $PWD$file" + if [ $line != "null" ] && [ -f $line ]; then + file=$(replaceGlobals $line) + VALUE_FILES="$VALUE_FILES -f $PWD$file" fi done for line in $appValueFiles; do - if [ $line != "null" ]; then - file=$(replaceGlobals $line) - VALUE_FILES="$VALUE_FILES -f $PWD$file" + if [ $line != "null" ] && [ -f $line ]; then + file=$(replaceGlobals $line) + VALUE_FILES="$VALUE_FILES -f $PWD$file" fi done From e6241d9b163d147837b2fa409a4ed776a8b695a1 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 25 Mar 2024 18:46:21 +0100 Subject: [PATCH 004/222] Do not error out in preview when kustomize: true When `kustomize: true` simply take the path and call `kustomize build `. In any other case keep using helm for templating. Before: ... + common/scripts/preview.sh hub compliance-operator https://github.com/mbaldessari/multicloud-gitops.git preview-fixes Error: Chart.yaml file is missing After: ... + common/scripts/preview.sh hub compliance-operator https://github.com/mbaldessari/multicloud-gitops.git preview-fixes apiVersion: console.openshift.io/v1 kind: ConsoleNotification metadata: name: purpose-banner spec: backgroundColor: '#ff0000' color: '#fff' location: BannerTop text: HUBOPS --- scripts/preview.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/preview.sh b/scripts/preview.sh index 2d8079cf..762a8ec5 100755 --- a/scripts/preview.sh +++ b/scripts/preview.sh @@ -57,6 +57,7 @@ CLUSTER_OPTS="$CLUSTER_OPTS --set global.clusterPlatform=$platform" sharedValueFiles=$(yq ".clusterGroup.sharedValueFiles" values-$SITE.yaml) appValueFiles=$(yq ".clusterGroup.applications.$APP.extraValueFiles" values-$SITE.yaml) +isKustomize=$(yq ".clusterGroup.applications.$APP.kustomize" values-$SITE.yaml) OVERRIDES=$( getOverrides ) VALUE_FILES="" @@ -75,5 +76,11 @@ for line in $appValueFiles; do fi done -cmd="helm template $chart --name-template ${APP} -n ${namespace} ${VALUE_FILES} ${OVERRIDES} ${CLUSTER_OPTS}" -eval "$cmd" +if [ $isKustomize == "true" ]; then + kustomizePath=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) + cmd="kustomize build ${kustomizePath}" + eval "$cmd" +else + cmd="helm template $chart --name-template ${APP} -n ${namespace} ${VALUE_FILES} ${OVERRIDES} ${CLUSTER_OPTS}" + eval "$cmd" +fi From 8dee997ae865373ed7fcc395868001890281acfc Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Mon, 25 Mar 2024 14:45:47 -0500 Subject: [PATCH 005/222] Also pass EXTRA_PLAYBOOK_OPTS environment setting --- scripts/pattern-util.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index ea02b7ef..0d1b8fa4 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -55,6 +55,7 @@ fi podman run -it --rm --pull=newer \ --security-opt label=disable \ -e EXTRA_HELM_OPTS \ + -e EXTRA_PLAYBOOK_OPTS \ -e KUBECONFIG \ -v /etc/pki:/etc/pki:ro \ -v "${HOME}":"${HOME}" \ From dafd44b812ad2ea9fd2ab414198079abdfbb8602 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 26 Mar 2024 09:49:20 +0100 Subject: [PATCH 006/222] Use oc kustomize That is what we have inside the utility container, so let's just rely on that --- scripts/preview.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/preview.sh b/scripts/preview.sh index 762a8ec5..154e7bda 100755 --- a/scripts/preview.sh +++ b/scripts/preview.sh @@ -78,7 +78,7 @@ done if [ $isKustomize == "true" ]; then kustomizePath=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) - cmd="kustomize build ${kustomizePath}" + cmd="oc kustomize ${kustomizePath}" eval "$cmd" else cmd="helm template $chart --name-template ${APP} -n ${namespace} ${VALUE_FILES} ${OVERRIDES} ${CLUSTER_OPTS}" From a2c3a2e6e75ab5e3c769752b98c0f3a255b52e95 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 26 Mar 2024 10:09:51 +0100 Subject: [PATCH 007/222] Print out application being parsed for easier debugging --- scripts/preview-all.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/preview-all.sh b/scripts/preview-all.sh index 296e7dc8..9fdcd955 100755 --- a/scripts/preview-all.sh +++ b/scripts/preview-all.sh @@ -18,6 +18,7 @@ fi for cluster in ${ALL_CLUSTERS[@]}; do APPS=$( yq ".clusterGroup.applications.[].name" values-$cluster.yaml ) for app in $APPS; do + printf "# Parsing application $app from cluster $cluster\n" common/scripts/preview.sh $cluster $app $REPO $TARGET_BRANCH done done From c634054d9f19487ad9943a0f6d2328e579756482 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 27 Mar 2024 11:57:28 +0100 Subject: [PATCH 008/222] Add .global.secretStore.backend in the clustergroup schema It is currently not there even though we mention it in the values files. --- clustergroup/values.schema.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index e88fc5a9..0ab0fc37 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -153,6 +153,9 @@ }, "options": { "$ref": "#/definitions/Options" + }, + "secretStore": { + "$ref": "#/definitions/GlobalSecretStore" } }, "required": [ @@ -160,6 +163,18 @@ ], "title": "Global" }, + "GlobalSecretStore": { + "type": "object", + "additionalProperties": false, + "properties": { + "backend": { + "type": "string", + "description": "Name of the secrets backend", + "default": "vault" + } + }, + "title": "GlobalSecretsStore" + }, "GlobalGit": { "type": "object", "additionalProperties": true, From 5280f2ca9f6253245b7215bc2e724a778e96f183 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 28 Mar 2024 15:24:40 +0100 Subject: [PATCH 009/222] Fix check for secretStore.backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default function in helm is somewhat unintuitive: ❯ cat templates/test.yaml metadata: name: foo {{- if eq .Values.global.secretStore.backend "vault" | default "vault" }} label: vault_is_here {{- else }} labe: not_here {{- end }} ❯ helm template --set global.secretStore.backend=foo . metadata: name: foo label: vault_is_here No matter the value of .Values.global.secretStore.backend, the default branch takes over. So let's change this to something that is correct albeit somewhat less readable Tested as follows: # global.secretStore.backend unset ❯ helm template --set global.secretStore.backend=null common/clustergroup |grep unsealjob.yaml |wc -l 1 # global.secretStore.backend set to 'vault' ❯ helm template --set global.secretStore.backend=vault common/clustergroup |grep unsealjob.yaml |wc -l 1 # global.secretStore.backend set to 'kubernetes' ❯ helm template --set global.secretStore.backend=kubernetes common/clustergroup |grep unsealjob.yaml |wc -l 0 ❯ helm template --set global.secretStore.backend=vault golang-external-secrets |grep -- -backend name: vault-backend ❯ helm template --set global.secretStore.backend=null golang-external-secrets |grep -- -backend name: vault-backend ❯ helm template --set global.secretStore.backend=kubernetes golang-external-secrets |grep -- -backend name: kubernetes-backend --- clustergroup/templates/imperative/unsealjob.yaml | 4 +++- .../kubernetes/golang-external-secrets-hub-secretstore.yaml | 5 ++--- .../vault/golang-external-secrets-hub-secretstore.yaml | 5 ++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clustergroup/templates/imperative/unsealjob.yaml b/clustergroup/templates/imperative/unsealjob.yaml index 4db14be3..b251c5da 100644 --- a/clustergroup/templates/imperative/unsealjob.yaml +++ b/clustergroup/templates/imperative/unsealjob.yaml @@ -1,4 +1,6 @@ -{{- if eq .Values.global.secretStore.backend "vault" | default "vault" }} +{{/* If the backend is not set at all we default to "vault". See https://www.github.com/helm/helm/issues/3308 + why we avoid using the default function */}} +{{- if or (eq .Values.global.secretStore.backend "vault") (not (hasKey .Values.global.secretStore "backend")) }} {{- if not (eq .Values.enabled "plumbing") }} {{- if $.Values.clusterGroup.isHubCluster }} --- diff --git a/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-secretstore.yaml b/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-secretstore.yaml index 62253f1f..02128e9a 100644 --- a/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-secretstore.yaml +++ b/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-secretstore.yaml @@ -1,10 +1,9 @@ -{{- $backend := .Values.global.secretStore.backend | default "vault" }} -{{- if eq $backend "kubernetes" }} +{{- if eq .Values.global.secretStore.backend "kubernetes" }} --- apiVersion: external-secrets.io/v1beta1 kind: ClusterSecretStore metadata: - name: {{ $backend }}-backend + name: kubernetes-backend namespace: golang-external-secrets spec: provider: diff --git a/golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml b/golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml index 8fdd4ab0..59f55086 100644 --- a/golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml +++ b/golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml @@ -1,10 +1,9 @@ -{{- $backend := .Values.global.secretStore.backend | default "vault" }} -{{- if eq $backend "vault" }} +{{- if or (eq .Values.global.secretStore.backend "vault") (not (hasKey .Values.global.secretStore "backend")) }} --- apiVersion: external-secrets.io/v1beta1 kind: ClusterSecretStore metadata: - name: {{ $backend }}-backend + name: vault-backend namespace: golang-external-secrets spec: provider: From 8869f11989320d07700203b6d6d50a31ec064639 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 28 Mar 2024 18:45:13 +0100 Subject: [PATCH 010/222] Introduce a generic parameter override via the EXTRA_ARGS env variable This way a user can decide to modify the podman command line. For example to inject additional useful extra variables in the container. For example: export EXTRA_ARGS="-e OCP_DOMAIN" ./pattern-util.sh make preview-all.sh --- scripts/pattern-util.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 0d1b8fa4..0f865e0a 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -61,6 +61,7 @@ podman run -it --rm --pull=newer \ -v "${HOME}":"${HOME}" \ -v "${HOME}":/pattern-home \ ${PODMAN_ARGS} \ + ${EXTRA_ARGS} \ -w "$(pwd)" \ "$PATTERN_UTILITY_CONTAINER" \ $@ From ba583f569aa571827c82e498bcca15c98af7a3d3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 28 Mar 2024 18:51:11 +0100 Subject: [PATCH 011/222] Allow overriding the oc lookups in preview.sh This allows us to inject values to ease testing. Tested as follows: $ unset OCP_DOMAIN OCP_PLATFORM OCP_VERSION $ export EXTRA_ARGS="-e OCP_DOMAIN -e OCP_PLATFORM -e OCP_VERSION" $ ./pattern.sh make preview-all &> /tmp/1 $ export OCP_DOMAIN=adifferentdomain.foo $ ./pattern.sh make preview-all &> /tmp/2 # Templates have effectively changed the domain $ diff -u /tmp/1 /tmp/2 | wc -l 73 $ unset OCP_DOMAIN # Without the domain change the templates are unchanged $ ./pattern.sh make preview-all &> /tmp/3 $ diff -u /tmp/1 /tmp/3 | wc -l 0 Note: When using pattern.sh you will need to inject the env variables in the container via `export EXTRA_ARGS="-e OCP_PLATFORM -e OCP_VERSION -e OCP_DOMAIN"` --- scripts/preview.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/preview.sh b/scripts/preview.sh index 154e7bda..347a0cdd 100755 --- a/scripts/preview.sh +++ b/scripts/preview.sh @@ -17,9 +17,13 @@ chart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) namespace=$(yq ".clusterGroup.applications.$APP.namespace" values-$SITE.yaml) pattern=$(yq ".global.pattern" values-global.yaml) -platform=$(oc get Infrastructure.config.openshift.io/cluster -o jsonpath='{.spec.platformSpec.type}') -ocpversion=$(oc get clusterversion/version -o jsonpath='{.status.desired.version}' | awk -F. '{print $1"."$2}') -domain=$(oc get Ingress.config.openshift.io/cluster -o jsonpath='{.spec.domain}' | sed 's/^apps.//') +# You can override the default lookups by using OCP_{PLATFORM,VERSION,DOMAIN} +# Note that when using the utility container you need to pass in the above variables +# by export EXTRA_ARGS="-e OCP_PLATFORM -e OCP_VERSION -e OCP_DOMAIN" before +# invoking pattern-util.sh +platform=${OCP_PLATFORM:-$(oc get Infrastructure.config.openshift.io/cluster -o jsonpath='{.spec.platformSpec.type}')} +ocpversion=${OCP_VERSION:-$(oc get clusterversion/version -o jsonpath='{.status.desired.version}' | awk -F. '{print $1"."$2}')} +domain=${OCP_DOMAIN:-$(oc get Ingress.config.openshift.io/cluster -o jsonpath='{.spec.domain}' | sed 's/^apps.//')} function replaceGlobals() { output=$( echo $1 | sed -e 's/ //g' -e 's/\$//g' -e s@^-@@g -e s@\'@@g ) From 66d426dfb904a3099d747df9629ddaaed1d360a4 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 29 Mar 2024 11:25:05 +0100 Subject: [PATCH 012/222] Always include values-global.yaml and values-.yaml Those are the starting points for setting the values. Without this, for example, the rendering of common/acm on the hub is basically empty because clusterGroup.isHubCluster won't be true. --- scripts/preview.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/preview.sh b/scripts/preview.sh index 347a0cdd..a39b1046 100755 --- a/scripts/preview.sh +++ b/scripts/preview.sh @@ -64,7 +64,7 @@ appValueFiles=$(yq ".clusterGroup.applications.$APP.extraValueFiles" values-$SIT isKustomize=$(yq ".clusterGroup.applications.$APP.kustomize" values-$SITE.yaml) OVERRIDES=$( getOverrides ) -VALUE_FILES="" +VALUE_FILES="-f values-global.yaml -f values-$SITE.yaml" IFS=$'\n' for line in $sharedValueFiles; do if [ $line != "null" ] && [ -f $line ]; then From 4de8385661f99f88dc4757fae72d798de7dace4e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 29 Mar 2024 11:41:59 +0100 Subject: [PATCH 013/222] Add help and message clarifying that preview has certain limits --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0d5d0a36..c6c7539c 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,8 @@ help: ## This help message show: ## show the starting template without installing it helm template common/operator-install/ --name-template $(NAME) $(HELM_OPTS) -preview-all: +preview-all: ## (EXPERIMENTAL) Previews all applications on hub and managed clusters + @echo "NOTE: This is just a tentative approximation of rendering all hub and managed clusters templates" @common/scripts/preview-all.sh $(TARGET_REPO) $(TARGET_BRANCH) preview-%: From d7e913bca9bb6fc5313d20e1d56be64f894ebe97 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 29 Mar 2024 12:07:40 +0100 Subject: [PATCH 014/222] Add clustergroup support to preview target With this the preview all should be a lot more complete and useful. Closes: https://github.com/validatedpatterns/common/issues/452 --- scripts/preview-all.sh | 3 ++- scripts/preview.sh | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/scripts/preview-all.sh b/scripts/preview-all.sh index 9fdcd955..4bf59322 100755 --- a/scripts/preview-all.sh +++ b/scripts/preview-all.sh @@ -16,7 +16,8 @@ if [ $CLUSTER_INFO_RET -ne 0 ]; then fi for cluster in ${ALL_CLUSTERS[@]}; do - APPS=$( yq ".clusterGroup.applications.[].name" values-$cluster.yaml ) + # We always add clustergroup as it is the entry point and it gets special cased in preview.sh. + APPS="clustergroup $( yq ".clusterGroup.applications.[].name" values-$cluster.yaml )" for app in $APPS; do printf "# Parsing application $app from cluster $cluster\n" common/scripts/preview.sh $cluster $app $REPO $TARGET_BRANCH diff --git a/scripts/preview.sh b/scripts/preview.sh index a39b1046..d5e695e4 100755 --- a/scripts/preview.sh +++ b/scripts/preview.sh @@ -13,8 +13,13 @@ APP=$1; shift GIT_REPO=$1; shift GIT_BRANCH=$1; shift -chart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) -namespace=$(yq ".clusterGroup.applications.$APP.namespace" values-$SITE.yaml) +if [ "${APP}" != "clustergroup" ]; then + chart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) + namespace=$(yq ".clusterGroup.applications.$APP.namespace" values-$SITE.yaml) +else + chart="common/clustergroup" + namespace="openshift-operators" +fi pattern=$(yq ".global.pattern" values-global.yaml) # You can override the default lookups by using OCP_{PLATFORM,VERSION,DOMAIN} From dd25da002c36c035407c7f70485961fdbe5488c3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 29 Mar 2024 13:22:02 +0100 Subject: [PATCH 015/222] Fix preview when the application's index name is not the same as the name attribute This covers the following case: foobar: name: foo namespace: foo project: foo path: charts/all/foo The preview.sh script is passed the name attribute of the application `foo`. So now we first find the key which corresponds to the attribute name `foo` and then use that when looking up the other attributes like path, etc. Closes: https://github.com/validatedpatterns/multicloud-gitops/issues/351 --- scripts/preview.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/preview.sh b/scripts/preview.sh index d5e695e4..ac2cd5c8 100755 --- a/scripts/preview.sh +++ b/scripts/preview.sh @@ -9,14 +9,23 @@ # - Make output can be included in the YAML. SITE=$1; shift -APP=$1; shift +APPNAME=$1; shift GIT_REPO=$1; shift GIT_BRANCH=$1; shift -if [ "${APP}" != "clustergroup" ]; then +if [ "${APPNAME}" != "clustergroup" ]; then + # This covers the following case: + # foobar: + # name: foo + # namespace: foo + # project: foo + # path: charts/all/foo + # So we retrieve the actual index ("foobar") given the name attribute of the application + APP=$(yq ".clusterGroup.applications | with_entries(select(.value.name == \"$APPNAME\")) | keys | .[0]" values-$SITE.yaml) chart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) namespace=$(yq ".clusterGroup.applications.$APP.namespace" values-$SITE.yaml) else + APP=$APPNAME chart="common/clustergroup" namespace="openshift-operators" fi From 4ec9d3e3f3808ef4a17e66c7827b8a6a6c2f5b08 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 8 Apr 2024 21:21:36 +0200 Subject: [PATCH 016/222] Force strings in extraParametersNested Otherwise if we pass a boolean in the extraParametersNested we will get: spec.source.helm.parameters[10].value: Invalid value: "boolean": spec.source.helm.parameters[10].value in body must be of type string: "boolean" --- clustergroup/templates/plumbing/applications.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clustergroup/templates/plumbing/applications.yaml b/clustergroup/templates/plumbing/applications.yaml index 3706d839..dbfefa8f 100644 --- a/clustergroup/templates/plumbing/applications.yaml +++ b/clustergroup/templates/plumbing/applications.yaml @@ -105,7 +105,7 @@ spec: {{- end }} {{- range $k, $v := $.Values.extraParametersNested }} - name: {{ $k }} - value: {{ $v }} + value: {{ printf "%s" $v | quote }} {{- end }} {{- range .overrides }} - name: {{ .name }} @@ -184,7 +184,7 @@ spec: {{- end }} {{- range $k, $v := $.Values.extraParametersNested }} - name: {{ $k }} - value: {{ $v }} + value: {{ printf "%s" $v | quote }} {{- end }} {{- range .overrides }} - name: {{ .name }} @@ -251,7 +251,7 @@ spec: {{- end }} {{- range $k, $v := $.Values.extraParametersNested }} - name: {{ $k }} - value: {{ $v }} + value: {{ printf "%s" $v | quote }} {{- end }} {{- range .overrides }} - name: {{ .name }} From cb77e121b9fbb2c152d21552678253cb1bf1794b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 10 Apr 2024 13:50:28 +0200 Subject: [PATCH 017/222] In ACM policies do not use $ARGOCD_APP_SOURCE_* variables The reason for this is the following: When changing the repo on the hub (by editing the pattern), the expectation is that the repo change will replicate from the hub to the spokes managed by ACM. Today this is very unlikely to happen because changing the repo on the hub will not change the policy and so ACM will not reapply it on the spokes. (I believe there is like a daily repush that happens even when the policy has not changed, but that is way too slow to be relied upon). By using the actual variable the policy will actually change, ACM will notice this and push the change on the spokes. Found while testing disconnected mode. I am not replacing them everywhere because I am not sure yet if there are additional semantics in common/clustergroup that I am unaware of. --- acm/templates/policies/application-policies.yaml | 4 ++-- tests/acm-industrial-edge-hub.expected.yaml | 4 ++-- tests/acm-medical-diagnosis-hub.expected.yaml | 4 ++-- tests/acm-normal.expected.yaml | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 01082e54..68548893 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -52,9 +52,9 @@ spec: {{- end }} parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: {{ $.Values.global.repoURL }} - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: {{ $.Values.global.targetRevision }} - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 07593017..59c7e60f 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -225,9 +225,9 @@ spec: - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 959fbe30..3a65a6be 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -216,9 +216,9 @@ spec: - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 87071cc4..af97f532 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -619,9 +619,9 @@ spec: - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -715,9 +715,9 @@ spec: - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern From 8dbb5ff7809f39d6b80874f762c4bad22cd09730 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 20 Feb 2024 21:20:42 +0100 Subject: [PATCH 018/222] Add support for custom CAs This feature relies on the VP operator version >= 0.0.44 in order to work. The way to enable this is to add a feature flag called 'initcontainers' in the VP operator. Once this is enabled, we will detect this and take over the all ArgoCD instances' definition and add initContainers which will inject the CAs contained in the trusted-bundle-ca configmap and also the openshift internal CA. Testing protocol: 1. (Operator 0.0.44) MCG deployment with experimentalCapabilities set to '' and using a github main upstream (i.e. without this PR) 2. (Operator 0.0.44) MCG deployment with experimentalCapabilities set to 'initcontainers' and using a github diconnected common upstream (requiring a custom CA) (i.e. with this PR) 3. (Operator 0.0.44) MCG deployment with experimentalCapabilities set to '' and using a github diconnected common upstream. (same as 1.2) and then set the initcontainer capability on the hub. Checked that the .global.experimentalCapabilities property replicated from hub to spoke and the initcontainers have been generated correctly 3.1 (Operator 0.0.44) Change the repo from github to an internal one that does need the custom ca to work 4. (Operator 0.0.43) Test an old operator with a newer common that contains this very branch Note: Once we will make initcontainers a default feature of the operator we will remove the ifs added in this PR and just make it the defaut behaviour. --- .../policies/application-policies.yaml | 3 + acm/templates/policies/ocp-gitops-policy.yaml | 167 ++++++++++++++++++ clustergroup/templates/_helpers.tpl | 2 + .../templates/imperative/_helpers.tpl | 103 ++++++++++- .../templates/imperative/configmap.yaml | 9 + clustergroup/templates/imperative/job.yaml | 21 ++- .../templates/imperative/unsealjob.yaml | 22 ++- clustergroup/templates/plumbing/argocd.yaml | 43 +++++ .../plumbing/trusted-bundle-ca-configmap.yaml | 7 + 9 files changed, 366 insertions(+), 11 deletions(-) create mode 100644 clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 68548893..925915c8 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -1,4 +1,5 @@ # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io +{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} {{- range .Values.clusterGroup.managedClusterGroups }} {{- $group := . }} {{- if not .hostedArgoSites }} @@ -75,6 +76,8 @@ spec: value: {{ $.Values.global.clusterPlatform }} - name: clusterGroup.name value: {{ $group.name }} + - name: global.experimentalCapabilities + value: {{ $.Values.global.experimentalCapabilities }} {{- range .helmOverrides }} - name: {{ .name }} value: {{ .value | quote }} diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index a0ed611f..f46b30c6 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -1,3 +1,4 @@ +{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: @@ -24,6 +25,15 @@ spec: include: - default object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -44,6 +54,163 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" +{{- if $hasInitContainerCapability }} + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.access.redhat.com/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} +{{- end }}{{/* if hasInitContainerCapability */}} --- apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index 83b06a04..cd0f5e8f 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -22,6 +22,8 @@ Default always defined top-level variables for helm charts value: {{ coalesce $.Values.global.localClusterDomain $.Values.global.hubClusterDomain }} - name: global.privateRepo value: {{ $.Values.global.privateRepo | quote }} +- name: global.experimentalCapabilities + value: {{ $.Values.global.experimentalCapabilities | default "" }} {{- end }} {{/* clustergroup.globalvaluesparameters */}} diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index f75e781e..64786acf 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -4,6 +4,29 @@ # 3. If it is an http secret, generate the correct URL # 4. If it is an ssh secret, create the private ssh key and make sure the git clone works +{{/* fetch-ca InitContainer */}} +{{- define "imperative.initcontainers.fetch-ca" }} +- name: fetch-ca + image: {{ $.Values.clusterGroup.imperative.image }} + imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles +{{- end }} + {{/* git-init InitContainer */}} {{- define "imperative.initcontainers.gitinit" }} - name: git-init @@ -12,6 +35,9 @@ env: - name: HOME value: /git/home + volumeMounts: + - name: git + mountPath: "/git" command: - 'sh' - '-c' @@ -37,11 +63,47 @@ mkdir /git/{repo,home}; git clone --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; +{{- end }} + +{{/* git-init-ca InitContainer */}} +{{- define "imperative.initcontainers.gitinit-ca" }} +- name: git-init + image: {{ $.Values.clusterGroup.imperative.image }} + imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} + env: + - name: HOME + value: /git/home volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs + command: + - 'sh' + - '-c' + - >- + if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then + URL="{{ $.Values.global.repoURL }}"; + else + if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode}}` }}' &>/dev/null; then + U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.username | base64decode }}` }}')"; + P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.password | base64decode }}` }}')"; + URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); + echo "USER/PASS: ${URL}"; + else + S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode }}` }}')"; + mkdir -p --mode 0700 "${HOME}/.ssh"; + echo "${S}" > "${HOME}/.ssh/id_rsa"; + chmod 0600 "${HOME}/.ssh/id_rsa"; + URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1git@/"); + git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; + echo "SSH: ${URL}"; + fi; + fi; + mkdir /git/{repo,home}; + git clone --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; + chmod 0770 /git/{repo,home}; {{- end }} - {{/* Final done container */}} {{- define "imperative.containers.done" }} - name: "done" @@ -56,6 +118,19 @@ {{- end }} {{/* volume-mounts for all containers */}} +{{- define "imperative.volumemounts_ca" }} +- name: git + mountPath: "/git" +- name: values-volume + mountPath: /values/values.yaml + subPath: values.yaml +- mountPath: /var/run/kube-root-ca + name: kube-root-ca +- mountPath: /var/run/trusted-ca + name: trusted-ca-bundle +- mountPath: /tmp/ca-bundles + name: ca-bundles +{{- end }} {{- define "imperative.volumemounts" }} - name: git mountPath: "/git" @@ -63,3 +138,29 @@ mountPath: /values/values.yaml subPath: values.yaml {{- end }} + +{{/* volumes for all containers */}} +{{- define "imperative.volumes" }} +- name: git + emptyDir: {} +- name: values-volume + configMap: + name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} +{{- end }} + +{{- define "imperative.volumes_ca" }} +- name: git + emptyDir: {} +- name: values-volume + configMap: + name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} +- configMap: + name: kube-root-ca.crt + name: kube-root-ca +- configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle +- name: ca-bundles + emptyDir: {} +{{- end }} diff --git a/clustergroup/templates/imperative/configmap.yaml b/clustergroup/templates/imperative/configmap.yaml index 8ca5a176..9f2d6155 100644 --- a/clustergroup/templates/imperative/configmap.yaml +++ b/clustergroup/templates/imperative/configmap.yaml @@ -9,4 +9,13 @@ metadata: data: values.yaml: | {{ tpl $valuesyaml . | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: trusted-ca-bundle + namespace: {{ $.Values.clusterGroup.imperative.namespace}} + annotations: + labels: + config.openshift.io/inject-trusted-cabundle: 'true' {{- end }} diff --git a/clustergroup/templates/imperative/job.yaml b/clustergroup/templates/imperative/job.yaml index cb092649..0b82d47c 100644 --- a/clustergroup/templates/imperative/job.yaml +++ b/clustergroup/templates/imperative/job.yaml @@ -1,3 +1,5 @@ +{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} + {{- if not (eq .Values.enabled "plumbing") }} {{/* Define this if needed (jobs defined */}} {{- if (and $.Values.clusterGroup.imperative (gt (len $.Values.clusterGroup.imperative.jobs) 0)) -}} @@ -22,7 +24,12 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there +{{- if $hasInitContainerCapability }} + {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} + {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} +{{- else }} {{- include "imperative.initcontainers.gitinit" . | indent 12 }} +{{- end }} {{- range $.Values.clusterGroup.imperative.jobs }} {{- if ne (.disabled | default "false" | toString | lower ) "true" }} - name: {{ .name }} @@ -53,17 +60,21 @@ spec: {{- end }} - {{ .playbook }} volumeMounts: +{{- if $hasInitContainerCapability }} + {{- include "imperative.volumemounts_ca" . | indent 16 }} +{{- else }} {{- include "imperative.volumemounts" . | indent 16 }} +{{- end }} {{- end }} {{- end }} containers: {{- include "imperative.containers.done" . | indent 12 }} volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} +{{- if $hasInitContainerCapability }} + {{- include "imperative.volumes_ca" . | indent 12 }} +{{- else }} + {{- include "imperative.volumes" . | indent 12 }} +{{- end }} restartPolicy: Never {{- end }} {{- end }} diff --git a/clustergroup/templates/imperative/unsealjob.yaml b/clustergroup/templates/imperative/unsealjob.yaml index b251c5da..e0ff2c78 100644 --- a/clustergroup/templates/imperative/unsealjob.yaml +++ b/clustergroup/templates/imperative/unsealjob.yaml @@ -1,3 +1,5 @@ +{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} + {{/* If the backend is not set at all we default to "vault". See https://www.github.com/helm/helm/issues/3308 why we avoid using the default function */}} {{- if or (eq .Values.global.secretStore.backend "vault") (not (hasKey .Values.global.secretStore "backend")) }} @@ -24,7 +26,13 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there +{{- if $hasInitContainerCapability }} + + {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} + {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} +{{- else }} {{- include "imperative.initcontainers.gitinit" . | indent 12 }} +{{- end }} - name: unseal-playbook image: {{ $.Values.clusterGroup.imperative.image }} imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} @@ -47,15 +55,19 @@ spec: - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - "common/ansible/playbooks/vault/vault.yaml" volumeMounts: +{{- if $hasInitContainerCapability }} + {{- include "imperative.volumemounts_ca" . | indent 16 }} +{{- else }} {{- include "imperative.volumemounts" . | indent 16 }} +{{- end }} containers: {{- include "imperative.containers.done" . | indent 12 }} volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} +{{- if $hasInitContainerCapability }} + {{- include "imperative.volumes_ca" . | indent 12 }} +{{- else }} + {{- include "imperative.volumes" . | indent 12 }} +{{- end }} restartPolicy: Never {{- end }} {{- end }} diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml index 12e362aa..dcce1b4b 100644 --- a/clustergroup/templates/plumbing/argocd.yaml +++ b/clustergroup/templates/plumbing/argocd.yaml @@ -1,3 +1,5 @@ +{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} + {{- if (eq .Values.enabled "all") }} {{- $namespace := print $.Values.global.pattern "-" $.Values.clusterGroup.name }} apiVersion: argoproj.io/v1beta1 @@ -68,9 +70,50 @@ spec: rbac: defaultPolicy: role:admin repo: +{{- if $hasInitContainerCapability }} + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: {{ $.Values.clusterGroup.imperative.image }} + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles +{{- if len $.Values.clusterGroup.argoCD.initContainers }} +{{ $.Values.clusterGroup.argoCD.initContainers | toPrettyJson }} +{{- end }} +{{- else }} {{- if len $.Values.clusterGroup.argoCD.initContainers }} initContainers: {{ $.Values.clusterGroup.argoCD.initContainers | toPrettyJson }} {{- end }} +{{- end }}{{/* if $hasInitContainerCapability */}} {{- if len $.Values.clusterGroup.argoCD.configManagementPlugins }} sidecarContainers: {{- range $cmp := $.Values.clusterGroup.argoCD.configManagementPlugins }} diff --git a/clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml b/clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml new file mode 100644 index 00000000..8b2a9cde --- /dev/null +++ b/clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml @@ -0,0 +1,7 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: trusted-ca-bundle + namespace: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }} + labels: + config.openshift.io/inject-trusted-cabundle: 'true' From 4e75d71f061dc2c9ba2826fc74549fcb83149a48 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 11 Apr 2024 18:12:05 +0200 Subject: [PATCH 019/222] Update tests --- .../acm-industrial-edge-factory.expected.yaml | 9 +++ tests/acm-industrial-edge-hub.expected.yaml | 11 +++ tests/acm-medical-diagnosis-hub.expected.yaml | 11 +++ tests/acm-naked.expected.yaml | 9 +++ tests/acm-normal.expected.yaml | 13 +++ ...roup-industrial-edge-factory.expected.yaml | 39 ++++++--- ...tergroup-industrial-edge-hub.expected.yaml | 69 +++++++++++----- ...rgroup-medical-diagnosis-hub.expected.yaml | 81 ++++++++++++++----- tests/clustergroup-naked.expected.yaml | 37 ++++++--- tests/clustergroup-normal.expected.yaml | 59 +++++++++----- 10 files changed, 266 insertions(+), 72 deletions(-) diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index 66c0c0b9..0291231a 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -89,6 +89,15 @@ spec: include: - default object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 59c7e60f..a912f0cd 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -248,6 +248,8 @@ spec: value: aws - name: clusterGroup.name value: factory + - name: global.experimentalCapabilities + value: - name: clusterGroup.isHubCluster value: "false" destination: @@ -296,6 +298,15 @@ spec: include: - default object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 3a65a6be..3ac5fe17 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -239,6 +239,8 @@ spec: value: aws - name: clusterGroup.name value: region-one + - name: global.experimentalCapabilities + value: - name: clusterGroup.isHubCluster value: "false" destination: @@ -287,6 +289,15 @@ spec: include: - default object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml index 880ef747..4f0ac751 100644 --- a/tests/acm-naked.expected.yaml +++ b/tests/acm-naked.expected.yaml @@ -90,6 +90,15 @@ spec: include: - default object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index af97f532..1a3f6e72 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -642,6 +642,8 @@ spec: value: aws - name: clusterGroup.name value: acm-edge + - name: global.experimentalCapabilities + value: - name: clusterGroup.isHubCluster value: "false" destination: @@ -738,6 +740,8 @@ spec: value: aws - name: clusterGroup.name value: acm-provision-edge + - name: global.experimentalCapabilities + value: - name: clusterGroup.isHubCluster value: "false" destination: @@ -786,6 +790,15 @@ spec: include: - default object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 851119a8..39ec60c7 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -198,6 +198,16 @@ data: kind: ClusterSecretStore name: vault-backend --- +# Source: clustergroup/templates/imperative/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: trusted-ca-bundle + namespace: imperative + annotations: + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- # Source: clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml kind: ConfigMap apiVersion: v1 @@ -230,6 +240,15 @@ data: --set clusterGroup.name=factory --post-renderer ./kustomize"] --- +# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml +kind: ConfigMap +apiVersion: v1 +metadata: + name: trusted-ca-bundle + namespace: mypattern-factory + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- # Source: clustergroup/templates/imperative/clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -359,6 +378,9 @@ spec: env: - name: HOME value: /git/home + volumeMounts: + - name: git + mountPath: "/git" command: - 'sh' - '-c' @@ -384,9 +406,6 @@ spec: mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -419,12 +438,12 @@ spec: - 'echo' - 'done' - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-factory + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: helm-values-configmap-factory restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -527,6 +546,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 611ecbb7..8355852c 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -359,6 +359,16 @@ data: kind: ClusterSecretStore name: vault-backend --- +# Source: clustergroup/templates/imperative/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: trusted-ca-bundle + namespace: imperative + annotations: + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- # Source: clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml kind: ConfigMap apiVersion: v1 @@ -391,6 +401,15 @@ data: --set clusterGroup.name=datacenter --post-renderer ./kustomize"] --- +# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml +kind: ConfigMap +apiVersion: v1 +metadata: + name: trusted-ca-bundle + namespace: mypattern-datacenter + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- # Source: clustergroup/templates/imperative/clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -520,6 +539,9 @@ spec: env: - name: HOME value: /git/home + volumeMounts: + - name: git + mountPath: "/git" command: - 'sh' - '-c' @@ -545,9 +567,6 @@ spec: mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -580,12 +599,12 @@ spec: - 'echo' - 'done' - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-datacenter + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: helm-values-configmap-datacenter restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -615,6 +634,9 @@ spec: env: - name: HOME value: /git/home + volumeMounts: + - name: git + mountPath: "/git" command: - 'sh' - '-c' @@ -640,9 +662,6 @@ spec: mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -677,12 +696,12 @@ spec: - 'echo' - 'done' - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-datacenter + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: helm-values-configmap-datacenter restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -821,6 +840,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: ignoreDifferences: [ { "group": "internal.open-cluster-management.io", @@ -884,6 +905,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -938,6 +961,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -992,6 +1017,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: ignoreDifferences: [ { "group": "apps", @@ -1076,6 +1103,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -1130,6 +1159,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -1211,6 +1242,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: - name: global.openshift value: "true" - name: injector.enabled diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 9855500c..819e2ef1 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -318,6 +318,25 @@ data: kind: ClusterSecretStore name: vault-backend --- +# Source: clustergroup/templates/imperative/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: trusted-ca-bundle + namespace: imperative + annotations: + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml +kind: ConfigMap +apiVersion: v1 +metadata: + name: trusted-ca-bundle + namespace: mypattern-hub + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- # Source: clustergroup/templates/imperative/clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -447,6 +466,9 @@ spec: env: - name: HOME value: /git/home + volumeMounts: + - name: git + mountPath: "/git" command: - 'sh' - '-c' @@ -472,9 +494,6 @@ spec: mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -507,12 +526,12 @@ spec: - 'echo' - 'done' - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-hub + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: helm-values-configmap-hub restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -542,6 +561,9 @@ spec: env: - name: HOME value: /git/home + volumeMounts: + - name: git + mountPath: "/git" command: - 'sh' - '-c' @@ -567,9 +589,6 @@ spec: mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -604,12 +623,12 @@ spec: - 'echo' - 'done' - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-hub + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: helm-values-configmap-hub restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -706,6 +725,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -760,6 +781,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -814,6 +837,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -868,6 +893,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -922,6 +949,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -976,6 +1005,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -1030,6 +1061,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -1084,6 +1117,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: - name: global.openshift value: "true" - name: injector.enabled @@ -1156,6 +1191,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -1210,6 +1247,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: @@ -1264,6 +1303,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: ignoreDifferences: [ { "group": "apps.openshift.io", @@ -1327,6 +1368,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: ignoreDifferences: [ { "group": "apps.openshift.io", @@ -1390,6 +1433,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 194bfa8f..b8e329d6 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -83,6 +83,25 @@ data: kind: ClusterSecretStore name: vault-backend --- +# Source: clustergroup/templates/imperative/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: trusted-ca-bundle + namespace: imperative + annotations: + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml +kind: ConfigMap +apiVersion: v1 +metadata: + name: trusted-ca-bundle + namespace: common-example + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- # Source: clustergroup/templates/imperative/clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -212,6 +231,9 @@ spec: env: - name: HOME value: /git/home + volumeMounts: + - name: git + mountPath: "/git" command: - 'sh' - '-c' @@ -237,9 +259,6 @@ spec: mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -274,12 +293,12 @@ spec: - 'echo' - 'done' - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: helm-values-configmap-example restartPolicy: Never --- # Source: clustergroup/templates/plumbing/argocd.yaml diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index f038446d..b3387af2 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -280,6 +280,25 @@ data: kind: ClusterSecretStore name: vault-backend --- +# Source: clustergroup/templates/imperative/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: trusted-ca-bundle + namespace: imperative + annotations: + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml +kind: ConfigMap +apiVersion: v1 +metadata: + name: trusted-ca-bundle + namespace: mypattern-example + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- # Source: clustergroup/templates/imperative/clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -409,6 +428,9 @@ spec: env: - name: HOME value: /git/home + volumeMounts: + - name: git + mountPath: "/git" command: - 'sh' - '-c' @@ -434,9 +456,6 @@ spec: mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -469,12 +488,12 @@ spec: - 'echo' - 'done' - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: helm-values-configmap-example restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -504,6 +523,9 @@ spec: env: - name: HOME value: /git/home + volumeMounts: + - name: git + mountPath: "/git" command: - 'sh' - '-c' @@ -529,9 +551,6 @@ spec: mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -566,12 +585,12 @@ spec: - 'echo' - 'done' - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: helm-values-configmap-example restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -670,6 +689,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: ignoreDifferences: [ { "group": "internal.open-cluster-management.io", @@ -736,6 +757,8 @@ spec: value: apps.region.example.com - name: global.privateRepo value: + - name: global.experimentalCapabilities + value: syncPolicy: automated: {} retry: From 9b965559c08931f5625aea50772f8d3a97f12b94 Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Thu, 11 Apr 2024 14:58:13 -0600 Subject: [PATCH 020/222] Support for issue #459 The changes here support the "Support for merging of namespaces, projects, subscriptions and application in overrides/values-common.yaml #459" issue that was opened by Northrop Grumman Files that were changed are: clustergroup/templates/_helpers.tpl clustergroup/templates/core/namespaces.yaml clustergroup/templates/core/operatorgroup.yaml clustergroup/templates/plumbing/projects.yaml clustergroup/values.schema.json examples/values-example.yaml The idea is that if you define the projects section, or the namespaces section, in two different values files using a map construct we will be able to merge both definition of projects into the final rendering of the manifests. The new structure for projects is as follows: ``` clusterGroup: ... projects: project1: ``` The new structure for namespaces is as follows: ``` clusterGroup: ... namespaces: namespace1: open-cluster-management: labels: openshift.io/node-selector: "" kubernetes.io/os: linux annotations: openshift.io/cluster-monitoring: "true" owner: "namespace owner" ``` The user would need to choose to use a list or a hashmap object. The user would not be able to use a mix of hashes and list to describe projects or namespaces. --- clustergroup/templates/_helpers.tpl | 152 ++++++++++++++++++ clustergroup/templates/core/namespaces.yaml | 10 ++ .../templates/core/operatorgroup.yaml | 10 ++ clustergroup/templates/plumbing/projects.yaml | 14 +- clustergroup/values.schema.json | 18 ++- examples/values-example.yaml | 18 +++ 6 files changed, 218 insertions(+), 4 deletions(-) diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index 83b06a04..7e764655 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -70,3 +70,155 @@ Default always defined valueFiles to be included in Applications but with a pref {{- end }} {{/* range $.Values.global.extraValueFiles */}} {{- end }} {{/* if $.Values.global.extraValueFiles */}} {{- end }} {{/* clustergroup.app.globalvalues.prefixedvaluefiles */}} + +{{/* +Helper function to generate AppProject from a map object +Called from common/clustergroup/templates/plumbing/projects.yaml +*/}} +{{- define "clustergroup.template.plumbing.projects.map" -}} +{{- $projects := index . 0 }} +{{- $namespace := index . 1 }} +{{- $enabled := index . 2 }} +{{- range $k, $v := $projects}} +apiVersion: argoproj.io/v1alpha1 +kind: AppProject +metadata: + name: {{ $k }} +{{- if (eq $enabled "plumbing") }} + namespace: openshift-gitops +{{- else }} + namespace: {{ $namespace }} +{{- end }} +spec: + description: "Pattern {{ . }}" + destinations: + - namespace: '*' + server: '*' + clusterResourceWhitelist: + - group: '*' + kind: '*' + namespaceResourceWhitelist: + - group: '*' + kind: '*' + sourceRepos: + - '*' +status: {} +--- +{{- end }} +{{- end }} + +{{/* + Helper function to generate AppProject from a list object. + Called from common/clustergroup/templates/plumbing/projects.yaml +*/}} +{{- define "clustergroup.template.plumbing.projects.list" -}} +{{- $projects := index . 0 }} +{{- $namespace := index . 1 }} +{{- $enabled := index . 2 }} +{{- range $projects}} +apiVersion: argoproj.io/v1alpha1 +kind: AppProject +metadata: + name: {{ . }} +{{- if (eq $enabled "plumbing") }} + namespace: openshift-gitops +{{- else }} + namespace: {{ $namespace }} +{{- end }} +spec: + description: "Pattern {{ . }}" + destinations: + - namespace: '*' + server: '*' + clusterResourceWhitelist: + - group: '*' + kind: '*' + namespaceResourceWhitelist: + - group: '*' + kind: '*' + sourceRepos: + - '*' +status: {} +{{- end }} +{{- end }} + +{{/* + Helper function to generate Namespaces from a map object. + Arguments passed as a list object are: + 0 - The namespace hash keys + 1 - Pattern name from .Values.global.pattern + 2 - Cluster group name from .Values.clusterGroup.name + Called from common/clustergroup/templates/core/namespaces.yaml +*/}} +{{- define "clustergroup.template.core.namespaces.map" -}} +{{- $ns := index . 0 }} +{{- $patternName := index . 1 }} +{{- $clusterGroupName := index . 2 }} + +{{- range $k, $v := $ns }}{{- /* We loop here even though the map has always just one key */}} +apiVersion: v1 +kind: Namespace +metadata: + name: {{ $k }} + {{- if ne $v nil }} + labels: + argocd.argoproj.io/managed-by: {{ $patternName }}-{{ .clusterGroupName }} + {{- if $v.labels }} + {{- range $key, $value := $v.labels }} {{- /* We loop here even though the map has always just one key */}} + {{ $key }}: {{ $value | default "" | quote }} + {{- end }} + {{- end }} + {{- if $v.annotations }} + annotations: + {{- range $key, $value := $v.annotations }} {{- /* We loop through the map to get key/value pairs */}} + {{ $key }}: {{ $value | default "" | quote }} + {{- end }} + {{- end }}{{- /* if $v.annotations */}} + {{- end }} +spec: +--- +{{- end }}{{- /* range $k, $v := $ns */}} +{{- end }} + +{{- /* + Helper function to generate OperatorGroup from a map object. + Arguments passed as a list object are: + 0 - The namespace hash keys + 1 - The operatorExcludes section from .Values.clusterGroup.operatorgroupExcludes + Called from common/clustergroup/templates/core/operatorgroup.yaml +*/ -}} +{{- define "clustergroup.template.core.operatorgroup.map" -}} +{{- $ns := index . 0 }} +{{- $operatorgroupExcludes := index . 1 }} +{{- if or (empty $operatorgroupExcludes) (not (has . $operatorgroupExcludes)) }} + {{- range $k, $v := $ns }}{{- /* We loop here even though the map has always just one key */}} + {{- if $v }} + {{- if $v.operatorGroup }}{{- /* Checks if the user sets operatorGroup: false */}} +apiVersion: operators.coreos.com/v1 +kind: OperatorGroup +metadata: + name: {{ $k }}-operator-group + namespace: {{ $k }} +spec: + targetNamespaces: + {{- if (hasKey $v "targetNamespaces") }} + {{- range $v.targetNamespaces }}{{- /* We loop through the list of tergetnamespaces */}} + - {{ . }} + {{- end }}{{- /* End range targetNamespaces */}} + {{- else }} + - {{ $k }} + {{- end }}{{- /* End of if hasKey $v "targetNamespaces" */}} + {{- end }}{{- /* End if $v.operatorGroup */}} + {{- else }}{{- /* else if $v == nil */}} +apiVersion: operators.coreos.com/v1 +kind: OperatorGroup +metadata: + name: {{ $k }}-operator-group + namespace: {{ $k }} +spec: + targetNamespaces: + - {{ $k }} + {{- end }}{{- /* end if $v */}} + {{- end }}{{- /* End range $k, $v = $ns */}} +{{- end }}{{- /* End of if operatorGroupExcludes */}} +{{- end }} {{- /* End define "clustergroup.template.core.operatorgroup.map" */}} diff --git a/clustergroup/templates/core/namespaces.yaml b/clustergroup/templates/core/namespaces.yaml index dfa6ae1a..c9a26afb 100644 --- a/clustergroup/templates/core/namespaces.yaml +++ b/clustergroup/templates/core/namespaces.yaml @@ -1,4 +1,13 @@ {{- if not (eq .Values.enabled "plumbing") }} +{{- /* + We first check if namespaces are defined as a map. If it is we call + our helper function in _helpers.tpl to process the namespaces + described in the values file. This is to support issue + https://github.com/validatedpatterns/common/issues/459 created by our customer. +*/ -}} +{{- if kindIs "map" .Values.clusterGroup.namespaces }} +{{- template "clustergroup.template.core.namespaces.map" (list .Values.clusterGroup.namespaces $.Values.global.pattern $.Values.clusterGroup.name) }} +{{- else }} {{- range $ns := .Values.clusterGroup.namespaces }} apiVersion: v1 kind: Namespace @@ -30,3 +39,4 @@ spec: --- {{- end }} {{- end }} +{{- end }} diff --git a/clustergroup/templates/core/operatorgroup.yaml b/clustergroup/templates/core/operatorgroup.yaml index cd679bd5..17aa966b 100644 --- a/clustergroup/templates/core/operatorgroup.yaml +++ b/clustergroup/templates/core/operatorgroup.yaml @@ -1,4 +1,13 @@ {{- if not (eq .Values.enabled "plumbing") }} +{{- /* + We first check if namespaces are defined as a map. If it is we call + our helper function in _helpers.tpl to process the projects + described in the values file. This is to support issue + https://github.com/validatedpatterns/common/issues/459 created by our customer. +*/ -}} +{{- if kindIs "map" .Values.clusterGroup.namespaces }} +{{- template "clustergroup.template.core.operatorgroup.map" (list .Values.clusterGroup.namespaces .Values.clusterGroup.operatorgroupExcludes) }} +{{- else }} {{- range $ns := .Values.clusterGroup.namespaces }} {{- if or (empty $.Values.clusterGroup.operatorgroupExcludes) (not (has . $.Values.clusterGroup.operatorgroupExcludes)) }} @@ -35,4 +44,5 @@ spec: --- {{- end }} {{- /* if or (empty $.Values.clusterGroup.operatorgroupExcludes) (not (has . $.Values.clusterGroup.operatorgroupExcludes)) */}} {{- end }} {{- /* range $ns := .Values.clusterGroup.namespaces */}} +{{- end }} {{- /* if kindIs "map" $ns */}} {{- end }} {{- /* if not (eq .Values.enabled "plumbing") */}} diff --git a/clustergroup/templates/plumbing/projects.yaml b/clustergroup/templates/plumbing/projects.yaml index 7f3b8c22..1050f2ee 100644 --- a/clustergroup/templates/plumbing/projects.yaml +++ b/clustergroup/templates/plumbing/projects.yaml @@ -1,5 +1,14 @@ {{- if not (eq .Values.enabled "core") }} {{- $namespace := print $.Values.global.pattern "-" $.Values.clusterGroup.name }} +{{- /* + We first check if projects are defined as a map. If it is we call + our helper function in _helpers.tpl to process the projects + described in the values file. This is to support issue + https://github.com/validatedpatterns/common/issues/459 created by our customer. +*/ -}} +{{- if kindIs "map" .Values.clusterGroup.projects }} +{{- template "clustergroup.template.plumbing.projects.map" (list .Values.clusterGroup.projects $namespace $.Values.enabled) }} +{{- else }} {{- range .Values.clusterGroup.projects }} apiVersion: argoproj.io/v1alpha1 kind: AppProject @@ -25,5 +34,6 @@ spec: - '*' status: {} --- -{{- end }} -{{- end }} +{{- end }} {{- /* end range */ -}} +{{- end }} {{- /* end if map */ -}} +{{- end }} {{- /* end if not "core" */ -}} diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 0ab0fc37..275a80a3 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -254,7 +254,14 @@ "description": "Templated value file paths." }, "namespaces": { - "type": "array", + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + } + ], "description": "This is the array of namespaces that the VP framework will create. In addition, operator groups will also be created for each namespace.", "items": { "$ref": "#/definitions/Namespaces" @@ -312,7 +319,14 @@ } }, "projects": { - "type": "array", + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + } + ], "description": "The list of projects that will be created in the ArgoCD instances.", "items": { "type": "string" diff --git a/examples/values-example.yaml b/examples/values-example.yaml index 6c006b00..84682e20 100644 --- a/examples/values-example.yaml +++ b/examples/values-example.yaml @@ -15,6 +15,18 @@ clusterGroup: - /values/{{ .Values.global.clusterPlatform }}.yaml - /values/{{ .Values.global.clusterVersion }}.yaml + # + # You can define namespaces using hashes and not as a list like so: + # namespaces: + # open-cluster-management: + # labels: + # openshift.io/node-selector: "" + # kubernetes.io/os: linux + # annotations: + # openshift.io/cluster-monitoring: "true" + # owner: "namespace owner" + # application-ci: + # You cannot mix list and hashes to define namespaces namespaces: - open-cluster-management: labels: @@ -58,6 +70,12 @@ clusterGroup: name: openshift-pipelines-operator-rh csv: redhat-openshift-pipelines.v1.5.2 + # + # You can define projects using hashes like so: + # projects: + # hub: + # datacenter: + # You cannot mix list and hashes to define projects. projects: - datacenter From 7128a3f3e583504c3127b96482a8b2c567247ae1 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 12 Apr 2024 12:01:48 +0200 Subject: [PATCH 021/222] Drop unused piece of schema json Not entirely sure how this slipped in. Reported-by: Martin Jackson --- clustergroup/values.schema.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 0ab0fc37..ac45b8a5 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -351,9 +351,6 @@ "items": { "$ref": "#/definitions/ManagedClusterGroup" } - }, - "externalClusters": { - "type": "array" } }, "required": [ From 36b2cb658ccfe848c6d3c2a07593366953eedccd Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sun, 14 Apr 2024 13:34:26 +0200 Subject: [PATCH 022/222] Small cleanup to remove unneeded log messages --- clustergroup/templates/imperative/_helpers.tpl | 4 ---- tests/clustergroup-industrial-edge-factory.expected.yaml | 2 -- tests/clustergroup-industrial-edge-hub.expected.yaml | 4 ---- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 4 ---- tests/clustergroup-naked.expected.yaml | 2 -- tests/clustergroup-normal.expected.yaml | 4 ---- 6 files changed, 20 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index 64786acf..1800b5fd 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -49,7 +49,6 @@ U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.username | base64decode }}` }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.password | base64decode }}` }}')"; URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode }}` }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -57,7 +56,6 @@ chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; @@ -89,7 +87,6 @@ U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.username | base64decode }}` }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.password | base64decode }}` }}')"; URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode }}` }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -97,7 +94,6 @@ chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 39ec60c7..3acb8a92 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -392,7 +392,6 @@ spec: U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -400,7 +399,6 @@ spec: chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 8355852c..c022acf5 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -553,7 +553,6 @@ spec: U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -561,7 +560,6 @@ spec: chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; @@ -648,7 +646,6 @@ spec: U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -656,7 +653,6 @@ spec: chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 819e2ef1..8d74bcb1 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -480,7 +480,6 @@ spec: U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -488,7 +487,6 @@ spec: chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; @@ -575,7 +573,6 @@ spec: U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -583,7 +580,6 @@ spec: chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index b8e329d6..842bf58b 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -245,7 +245,6 @@ spec: U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; URL=$(echo | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -253,7 +252,6 @@ spec: chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index b3387af2..1e5719d4 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -442,7 +442,6 @@ spec: U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -450,7 +449,6 @@ spec: chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; @@ -537,7 +535,6 @@ spec: U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; else S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; mkdir -p --mode 0700 "${HOME}/.ssh"; @@ -545,7 +542,6 @@ spec: chmod 0600 "${HOME}/.ssh/id_rsa"; URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; fi; fi; mkdir /git/{repo,home}; From 247ee651da63e3ecd2faaf56335a46270b2a77eb Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sun, 14 Apr 2024 13:46:50 +0200 Subject: [PATCH 023/222] Support for cluster-wide proxy If the clusterwide proxy object is configured, let's support it when we clone the git repos for the imperative framework. --- clustergroup/templates/imperative/_helpers.tpl | 12 ++++++++++++ ...lustergroup-industrial-edge-factory.expected.yaml | 6 ++++++ tests/clustergroup-industrial-edge-hub.expected.yaml | 12 ++++++++++++ .../clustergroup-medical-diagnosis-hub.expected.yaml | 12 ++++++++++++ tests/clustergroup-naked.expected.yaml | 6 ++++++ tests/clustergroup-normal.expected.yaml | 12 ++++++++++++ 6 files changed, 60 insertions(+) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index 1800b5fd..f28b5668 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -58,6 +58,12 @@ git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; @@ -96,6 +102,12 @@ git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 3acb8a92..da521518 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -401,6 +401,12 @@ spec: git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index c022acf5..f84bbebb 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -562,6 +562,12 @@ spec: git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; @@ -655,6 +661,12 @@ spec: git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 8d74bcb1..9effcbab 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -489,6 +489,12 @@ spec: git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; @@ -582,6 +588,12 @@ spec: git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 842bf58b..13e66fc8 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -254,6 +254,12 @@ spec: git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 1e5719d4..8d3d4d51 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -451,6 +451,12 @@ spec: git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; @@ -544,6 +550,12 @@ spec: git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; fi; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; + OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; + if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; From 86164c6a0da9860382ba54325565e4657e2903fb Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sun, 14 Apr 2024 14:09:15 +0200 Subject: [PATCH 024/222] Update ESO to 0.9.14 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.9.13.tgz | Bin 96126 -> 0 bytes .../charts/external-secrets-0.9.14.tgz | Bin 0 -> 99176 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 507 +++++++++++++++--- ...-secrets-industrial-edge-hub.expected.yaml | 507 +++++++++++++++--- ...ecrets-medical-diagnosis-hub.expected.yaml | 507 +++++++++++++++--- ...olang-external-secrets-naked.expected.yaml | 507 +++++++++++++++--- ...lang-external-secrets-normal.expected.yaml | 507 +++++++++++++++--- 9 files changed, 2239 insertions(+), 304 deletions(-) delete mode 100644 golang-external-secrets/charts/external-secrets-0.9.13.tgz create mode 100644 golang-external-secrets/charts/external-secrets-0.9.14.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index a2a2b061..6e2f5b00 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.0.3 dependencies: - name: external-secrets - version: "0.9.13" + version: "0.9.14" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.9.13.tgz b/golang-external-secrets/charts/external-secrets-0.9.13.tgz deleted file mode 100644 index 464befd970d337e51451d4871cd1a9aef6458da2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96126 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⁡Ve)YG||}Hk5Q1YGH8~ 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 J1K>vh_&-eMZIl22 literal 0 HcmV?d00001 diff --git a/golang-external-secrets/values.yaml b/golang-external-secrets/values.yaml index 42418202..bda2ce6c 100644 --- a/golang-external-secrets/values.yaml +++ b/golang-external-secrets/values.yaml @@ -37,10 +37,10 @@ clusterGroup: external-secrets: image: - tag: v0.9.13-ubi + tag: v0.9.14-ubi webhook: image: - tag: v0.9.13-ubi + tag: v0.9.14-ubi certController: image: - tag: v0.9.13-ubi + tag: v0.9.14-ubi diff --git a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml index 788f0ce4..0e5156a7 100644 --- a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml @@ -4,12 +4,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -17,12 +17,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -30,12 +30,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -43,12 +43,12 @@ apiVersion: v1 kind: Secret metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -1762,6 +1762,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -3026,6 +3066,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -3269,6 +3314,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -3600,6 +3673,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -3760,6 +3897,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -4332,6 +4509,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -6304,6 +6489,13 @@ spec: type: type: string type: object + updatePolicy: + default: Replace + description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' + enum: + - Replace + - IfNotExists + type: string required: - secretStoreRefs - selector @@ -6373,7 +6565,9 @@ spec: - match type: object type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. + description: |- + Synced PushSecrets, including secrets that already exist in provider. + Matches secret stores to PushSecretData that was stored to that secret store. type: object syncedResourceVersion: description: SyncedResourceVersion keeps track of the last synced version. @@ -7296,6 +7490,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -8560,6 +8794,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -8803,6 +9042,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -9134,6 +9401,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -9294,6 +9625,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -9866,6 +10237,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -10774,6 +11153,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -11139,10 +11526,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11206,10 +11593,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11315,10 +11702,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -11355,10 +11742,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -11399,10 +11786,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11420,10 +11807,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11431,7 +11818,7 @@ roleRef: name: golang-external-secrets-cert-controller subjects: - name: external-secrets-cert-controller - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml @@ -11440,10 +11827,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11451,7 +11838,7 @@ roleRef: name: golang-external-secrets-controller subjects: - name: golang-external-secrets - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml @@ -11474,12 +11861,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11513,12 +11900,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11527,19 +11914,19 @@ roleRef: subjects: - kind: ServiceAccount name: golang-external-secrets - namespace: "default" + namespace: default --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml apiVersion: v1 kind: Service metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -11558,12 +11945,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11575,10 +11962,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -11593,7 +11980,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -11621,12 +12008,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11638,10 +12025,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -11656,7 +12043,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -11671,12 +12058,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11688,10 +12075,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -11706,7 +12093,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -11786,7 +12173,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-secretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11802,7 +12189,7 @@ webhooks: scope: "Cluster" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-clustersecretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11826,7 +12213,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-externalsecret admissionReviewVersions: ["v1", "v1beta1"] diff --git a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml b/tests/golang-external-secrets-industrial-edge-hub.expected.yaml index 735d99f4..847a025e 100644 --- a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-hub.expected.yaml @@ -4,12 +4,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -17,12 +17,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -30,12 +30,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -43,12 +43,12 @@ apiVersion: v1 kind: Secret metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -1762,6 +1762,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -3026,6 +3066,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -3269,6 +3314,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -3600,6 +3673,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -3760,6 +3897,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -4332,6 +4509,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -6304,6 +6489,13 @@ spec: type: type: string type: object + updatePolicy: + default: Replace + description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' + enum: + - Replace + - IfNotExists + type: string required: - secretStoreRefs - selector @@ -6373,7 +6565,9 @@ spec: - match type: object type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. + description: |- + Synced PushSecrets, including secrets that already exist in provider. + Matches secret stores to PushSecretData that was stored to that secret store. type: object syncedResourceVersion: description: SyncedResourceVersion keeps track of the last synced version. @@ -7296,6 +7490,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -8560,6 +8794,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -8803,6 +9042,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -9134,6 +9401,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -9294,6 +9625,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -9866,6 +10237,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -10774,6 +11153,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -11139,10 +11526,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11206,10 +11593,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11315,10 +11702,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -11355,10 +11742,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -11399,10 +11786,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11420,10 +11807,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11431,7 +11818,7 @@ roleRef: name: golang-external-secrets-cert-controller subjects: - name: external-secrets-cert-controller - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml @@ -11440,10 +11827,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11451,7 +11838,7 @@ roleRef: name: golang-external-secrets-controller subjects: - name: golang-external-secrets - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml @@ -11474,12 +11861,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11513,12 +11900,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11527,19 +11914,19 @@ roleRef: subjects: - kind: ServiceAccount name: golang-external-secrets - namespace: "default" + namespace: default --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml apiVersion: v1 kind: Service metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -11558,12 +11945,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11575,10 +11962,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -11593,7 +11980,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -11621,12 +12008,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11638,10 +12025,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -11656,7 +12043,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -11671,12 +12058,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11688,10 +12075,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -11706,7 +12093,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -11786,7 +12173,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-secretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11802,7 +12189,7 @@ webhooks: scope: "Cluster" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-clustersecretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11826,7 +12213,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-externalsecret admissionReviewVersions: ["v1", "v1beta1"] diff --git a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml b/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml index 735d99f4..847a025e 100644 --- a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml +++ b/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml @@ -4,12 +4,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -17,12 +17,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -30,12 +30,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -43,12 +43,12 @@ apiVersion: v1 kind: Secret metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -1762,6 +1762,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -3026,6 +3066,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -3269,6 +3314,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -3600,6 +3673,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -3760,6 +3897,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -4332,6 +4509,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -6304,6 +6489,13 @@ spec: type: type: string type: object + updatePolicy: + default: Replace + description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' + enum: + - Replace + - IfNotExists + type: string required: - secretStoreRefs - selector @@ -6373,7 +6565,9 @@ spec: - match type: object type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. + description: |- + Synced PushSecrets, including secrets that already exist in provider. + Matches secret stores to PushSecretData that was stored to that secret store. type: object syncedResourceVersion: description: SyncedResourceVersion keeps track of the last synced version. @@ -7296,6 +7490,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -8560,6 +8794,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -8803,6 +9042,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -9134,6 +9401,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -9294,6 +9625,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -9866,6 +10237,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -10774,6 +11153,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -11139,10 +11526,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11206,10 +11593,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11315,10 +11702,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -11355,10 +11742,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -11399,10 +11786,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11420,10 +11807,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11431,7 +11818,7 @@ roleRef: name: golang-external-secrets-cert-controller subjects: - name: external-secrets-cert-controller - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml @@ -11440,10 +11827,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11451,7 +11838,7 @@ roleRef: name: golang-external-secrets-controller subjects: - name: golang-external-secrets - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml @@ -11474,12 +11861,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11513,12 +11900,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11527,19 +11914,19 @@ roleRef: subjects: - kind: ServiceAccount name: golang-external-secrets - namespace: "default" + namespace: default --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml apiVersion: v1 kind: Service metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -11558,12 +11945,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11575,10 +11962,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -11593,7 +11980,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -11621,12 +12008,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11638,10 +12025,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -11656,7 +12043,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -11671,12 +12058,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11688,10 +12075,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -11706,7 +12093,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -11786,7 +12173,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-secretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11802,7 +12189,7 @@ webhooks: scope: "Cluster" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-clustersecretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11826,7 +12213,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-externalsecret admissionReviewVersions: ["v1", "v1beta1"] diff --git a/tests/golang-external-secrets-naked.expected.yaml b/tests/golang-external-secrets-naked.expected.yaml index e09b409d..081ba464 100644 --- a/tests/golang-external-secrets-naked.expected.yaml +++ b/tests/golang-external-secrets-naked.expected.yaml @@ -4,12 +4,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -17,12 +17,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -30,12 +30,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -43,12 +43,12 @@ apiVersion: v1 kind: Secret metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -1762,6 +1762,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -3026,6 +3066,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -3269,6 +3314,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -3600,6 +3673,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -3760,6 +3897,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -4332,6 +4509,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -6304,6 +6489,13 @@ spec: type: type: string type: object + updatePolicy: + default: Replace + description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' + enum: + - Replace + - IfNotExists + type: string required: - secretStoreRefs - selector @@ -6373,7 +6565,9 @@ spec: - match type: object type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. + description: |- + Synced PushSecrets, including secrets that already exist in provider. + Matches secret stores to PushSecretData that was stored to that secret store. type: object syncedResourceVersion: description: SyncedResourceVersion keeps track of the last synced version. @@ -7296,6 +7490,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -8560,6 +8794,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -8803,6 +9042,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -9134,6 +9401,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -9294,6 +9625,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -9866,6 +10237,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -10774,6 +11153,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -11139,10 +11526,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11206,10 +11593,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11315,10 +11702,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -11355,10 +11742,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -11399,10 +11786,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11420,10 +11807,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11431,7 +11818,7 @@ roleRef: name: golang-external-secrets-cert-controller subjects: - name: external-secrets-cert-controller - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml @@ -11440,10 +11827,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11451,7 +11838,7 @@ roleRef: name: golang-external-secrets-controller subjects: - name: golang-external-secrets - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml @@ -11474,12 +11861,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11513,12 +11900,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11527,19 +11914,19 @@ roleRef: subjects: - kind: ServiceAccount name: golang-external-secrets - namespace: "default" + namespace: default --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml apiVersion: v1 kind: Service metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -11558,12 +11945,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11575,10 +11962,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -11593,7 +11980,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -11621,12 +12008,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11638,10 +12025,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -11656,7 +12043,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -11671,12 +12058,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11688,10 +12075,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -11706,7 +12093,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -11786,7 +12173,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-secretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11802,7 +12189,7 @@ webhooks: scope: "Cluster" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-clustersecretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11826,7 +12213,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-externalsecret admissionReviewVersions: ["v1", "v1beta1"] diff --git a/tests/golang-external-secrets-normal.expected.yaml b/tests/golang-external-secrets-normal.expected.yaml index 735d99f4..847a025e 100644 --- a/tests/golang-external-secrets-normal.expected.yaml +++ b/tests/golang-external-secrets-normal.expected.yaml @@ -4,12 +4,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -17,12 +17,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -30,12 +30,12 @@ apiVersion: v1 kind: ServiceAccount metadata: name: external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -43,12 +43,12 @@ apiVersion: v1 kind: Secret metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -1762,6 +1762,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -3026,6 +3066,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -3269,6 +3314,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -3600,6 +3673,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -3760,6 +3897,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -4332,6 +4509,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -6304,6 +6489,13 @@ spec: type: type: string type: object + updatePolicy: + default: Replace + description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' + enum: + - Replace + - IfNotExists + type: string required: - secretStoreRefs - selector @@ -6373,7 +6565,9 @@ spec: - match type: object type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. + description: |- + Synced PushSecrets, including secrets that already exist in provider. + Matches secret stores to PushSecretData that was stored to that secret store. type: object syncedResourceVersion: description: SyncedResourceVersion keeps track of the last synced version. @@ -7296,6 +7490,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object vault: description: Vault configures this store to sync secrets using Hashi provider properties: @@ -8560,6 +8794,11 @@ spec: properties: account: type: string + hostId: + description: |- + Optional HostID for JWT authentication. This may be used depending + on how the Conjur JWT authenticator policy is configured. + type: string secretRef: description: |- Optional SecretRef that refers to a key in a Secret resource containing JWT token to @@ -8803,6 +9042,34 @@ spec: required: - data type: object + fortanix: + description: Fortanix configures this store to sync secrets using the Fortanix provider + properties: + apiKey: + description: APIKey is the API token to access SDKMS Applications. + properties: + secretRef: + description: SecretRef is a reference to a secret containing the SDKMS API Key. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + apiUrl: + description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. + type: string + type: object gcpsm: description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider properties: @@ -9134,6 +9401,70 @@ spec: required: - auth type: object + onboardbase: + description: Onboardbase configures this store to sync secrets using the Onboardbase provider + properties: + apiHost: + default: https://public.onboardbase.com/api/v1/ + description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ + type: string + auth: + description: Auth configures how the Operator authenticates with the Onboardbase API + properties: + apiKeyRef: + description: |- + OnboardbaseAPIKey is the APIKey generated by an admin account. + It is used to recognize and authorize access to a project and environment within onboardbase + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + passcodeRef: + description: OnboardbasePasscode is the passcode attached to the API Key + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - apiKeyRef + - passcodeRef + type: object + environment: + default: development + description: Environment is the name of an environmnent within a project to pull the secrets from + type: string + project: + default: development + description: Project is an onboardbase project that the secrets should be pulled from + type: string + required: + - apiHost + - auth + - environment + - project + type: object onepassword: description: OnePassword configures this store to sync secrets using the 1Password Cloud provider properties: @@ -9294,6 +9625,46 @@ spec: - region - vault type: object + passworddepot: + description: Configures a store to sync secrets with a Password Depot instance. + properties: + auth: + description: Auth configures how secret-manager authenticates with a Password Depot instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + database: + description: Database to use as source + type: string + host: + description: URL configures the Password Depot instance URL. + type: string + required: + - auth + - database + - host + type: object pulumi: description: Pulumi configures this store to sync secrets using the Pulumi provider properties: @@ -9866,6 +10237,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -10774,6 +11153,14 @@ spec: - path - username type: object + namespace: + description: |- + Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. + Namespaces is a set of features within Vault Enterprise that allows + Vault environments to support Secure Multi-tenancy. e.g: "ns1". + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + This will default to Vault.Namespace field if set, or empty otherwise + type: string tokenSecretRef: description: TokenSecretRef authenticates with Vault by presenting a token. properties: @@ -11139,10 +11526,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11206,10 +11593,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11315,10 +11702,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -11355,10 +11742,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -11399,10 +11786,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11420,10 +11807,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11431,7 +11818,7 @@ roleRef: name: golang-external-secrets-cert-controller subjects: - name: external-secrets-cert-controller - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml @@ -11440,10 +11827,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11451,7 +11838,7 @@ roleRef: name: golang-external-secrets-controller subjects: - name: golang-external-secrets - namespace: "default" + namespace: default kind: ServiceAccount --- # Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml @@ -11474,12 +11861,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11513,12 +11900,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: golang-external-secrets-leaderelection - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -11527,19 +11914,19 @@ roleRef: subjects: - kind: ServiceAccount name: golang-external-secrets - namespace: "default" + namespace: default --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml apiVersion: v1 kind: Service metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -11558,12 +11945,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-cert-controller - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11575,10 +11962,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -11593,7 +11980,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -11621,12 +12008,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11638,10 +12025,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -11656,7 +12043,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -11671,12 +12058,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: golang-external-secrets-webhook - namespace: "default" + namespace: default labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -11688,10 +12075,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.13 + helm.sh/chart: external-secrets-0.9.14 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.13" + app.kubernetes.io/version: "v0.9.14" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -11706,7 +12093,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.14-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -11786,7 +12173,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-secretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11802,7 +12189,7 @@ webhooks: scope: "Cluster" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-clustersecretstore admissionReviewVersions: ["v1", "v1beta1"] @@ -11826,7 +12213,7 @@ webhooks: scope: "Namespaced" clientConfig: service: - namespace: "default" + namespace: default name: golang-external-secrets-webhook path: /validate-external-secrets-io-v1beta1-externalsecret admissionReviewVersions: ["v1", "v1beta1"] From f4bed3a35f9ddd3ed49ea59dc4a3d8a394ebe55a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 16 Apr 2024 07:04:01 +0200 Subject: [PATCH 025/222] Update CRD from operator v0.0.44 --- ...ops.hybrid-cloud-patterns.io_patterns.yaml | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml b/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml index 68be225f..b3d769bb 100644 --- a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml +++ b/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.14.0 name: patterns.gitops.hybrid-cloud-patterns.io spec: group: gitops.hybrid-cloud-patterns.io @@ -31,14 +31,19 @@ spec: description: Pattern is the Schema for the patterns API properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -51,9 +56,14 @@ spec: type: string clusterGroupName: type: string + experimentalCapabilities: + description: Comma separated capabilities to enable certain experimental + features + type: string extraParameters: - description: '.Name is dot separated per the helm --set syntax, such - as: global.something.field' + description: |- + .Name is dot separated per the helm --set syntax, such as: + global.something.field items: properties: name: @@ -105,9 +115,9 @@ spec: short-sha''s. Default: HEAD' type: string tokenSecret: - description: Optional. K8s secret name where the info for connecting - to git can be found. The supported secrets are modeled after - the private repositories in argo (https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#repositories) + description: |- + Optional. K8s secret name where the info for connecting to git can be found. The supported secrets are modeled after the + private repositories in argo (https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#repositories) currently ssh and username+password are supported type: string tokenSecretNamespace: @@ -121,18 +131,18 @@ spec: properties: clusterGroupChartGitRevision: default: main - description: The git reference when deploying the clustergroup - helm chart directly from a git repo Defaults to 'main'. (Only - used when developing the clustergroup helm chart) + description: |- + The git reference when deploying the clustergroup helm chart directly from a git repo + Defaults to 'main'. (Only used when developing the clustergroup helm chart) type: string clusterGroupChartVersion: description: Which chart version for the clustergroup helm chart. Defaults to "0.8.*" type: string clusterGroupGitRepoUrl: - description: The url when deploying the clustergroup helm chart - directly from a git repo Defaults to '' which means not used - (Only used when developing the clustergroup helm chart) + description: |- + The url when deploying the clustergroup helm chart directly from a git repo + Defaults to '' which means not used (Only used when developing the clustergroup helm chart) type: string enabled: default: true @@ -160,10 +170,11 @@ spec: type: string applications: items: - description: PatternApplicationInfo defines the Applications Status - for the Pattern. This structure is part of the PatternStatus as - an array The Application Status will be included as part of the - Observed state of Pattern + description: |- + PatternApplicationInfo defines the Applications + Status for the Pattern. + This structure is part of the PatternStatus as an array + The Application Status will be included as part of the Observed state of Pattern properties: healthMessage: type: string From 2319eea438e5931cf42b591b9501919dc8fd6227 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 16 Apr 2024 17:32:35 +0200 Subject: [PATCH 026/222] Expose main.experimentalCapabilities in operator-install --- operator-install/templates/pattern.yaml | 3 +++ operator-install/values.yaml | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index 3615d18d..8bf7761a 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -20,6 +20,9 @@ spec: {{- if .Values.main.analyticsUUID }} analyticsUUID: {{ .Values.main.analyticsUUID }} {{- end }} {{/* if .Values.main.analyticsUUID */}} +{{- if .Values.main.experimentalCapabilities }} + experimentalCapabilities: {{ .Values.main.experimentalCapabilities }} +{{- end }} {{/* if .Values.main.experimentalCapabilities */}} {{- if .Values.main.extraParameters }} extraParameters: {{- range .Values.main.extraParameters }} diff --git a/operator-install/values.yaml b/operator-install/values.yaml index 9c2f7386..28bc3d4b 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -13,6 +13,10 @@ main: multiSourceConfig: enabled: false + # String to enable certain experimental capabilities in the operator and the + # framework. Not needed unless you know exactly what you're doing. + experimentalCapabilities: "" + patternsOperator: channel: fast source: community-operators From 2ffb55fec01e945d805fbcdd00fdf07743daed3b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 16 Apr 2024 19:50:34 +0200 Subject: [PATCH 027/222] Release clustergroup v0.8.3 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 345b8175..367cea35 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.2 +version: 0.8.3 From f2215f746338b1c38f5fdfc2db096059935e8a4b Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 16 Apr 2024 17:41:21 -0400 Subject: [PATCH 028/222] feat: add support for hive clusterdeployments creating spokes Co-authored-by: Alejandro Villegas Signed-off-by: Tomer Figenblat --- .../provision/clusterdeployment.yaml | 71 +++++++++++++++++++ acm/templates/provision/clusterpool.yaml | 15 +--- .../provision/managedclusterset.yaml | 16 +++++ acm/templates/provision/secrets-aws.yaml | 65 +++++++++++------ acm/templates/provision/secrets-azure.yaml | 65 +++++++++++------ acm/templates/provision/secrets-common.yaml | 59 ++++++++++----- acm/values.yaml | 21 +++++- clustergroup/values.schema.json | 32 +++++++++ 8 files changed, 267 insertions(+), 77 deletions(-) create mode 100644 acm/templates/provision/clusterdeployment.yaml create mode 100644 acm/templates/provision/managedclusterset.yaml diff --git a/acm/templates/provision/clusterdeployment.yaml b/acm/templates/provision/clusterdeployment.yaml new file mode 100644 index 00000000..cc37c161 --- /dev/null +++ b/acm/templates/provision/clusterdeployment.yaml @@ -0,0 +1,71 @@ +{{- range .Values.clusterGroup.managedClusterGroups }} +{{- $group := . }} + +{{- range $group.clusterDeployments}} +{{ $cluster := . }} +{{- $deploymentName := print $cluster.name "-" $group.name }} + +{{- $cloud := "None" }} +{{- $region := "None" }} + +{{- if $cluster.platform.aws }} +{{- $cloud = "aws" }} +{{- $region = $cluster.platform.aws.region }} +{{- else if $cluster.platform.azure }} +{{- $cloud = "azure" }} +{{- $region = $cluster.platform.azure.region }} +{{- end }} + +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ $deploymentName }} + +--- +apiVersion: hive.openshift.io/v1 +kind: ClusterDeployment +metadata: + name: {{ $deploymentName }} + namespace: {{ $deploymentName }} + labels: + vendor: OpenShift +spec: + baseDomain: {{ $cluster.baseDomain }} + clusterName: {{ $deploymentName }} + installAttemptsLimit: 1 + platform: + {{ $cloud }}: + credentialsSecretRef: + name: {{ $deploymentName }}-creds + region: {{ $region }} + provisioning: + installConfigSecretRef: + name: {{ $deploymentName }}-install-config + sshPrivateKeySecretRef: + name: {{ $deploymentName }}-ssh-private-key + imageSetRef: + name: img{{ $cluster.openshiftVersion }}-multi-appsub + pullSecretRef: + name: {{ $deploymentName }}-pull-secret + +--- +apiVersion: cluster.open-cluster-management.io/v1 +kind: ManagedCluster +metadata: + labels: + cluster.open-cluster-management.io/clusterset: {{ $group.name }} + {{- if (not $group.acmlabels) }} + clusterGroup: {{ $group.name }} + {{- else if eq (len $group.acmlabels) 0 }} + clusterGroup: {{ $group.name }} + {{- else }} + {{- range $group.acmlabels }} + {{ .name }}: {{ .value }} + {{- end }} + {{- end }} + name: {{ $deploymentName }} +spec: + hubAcceptsClient: true +{{- end }}{{- /* range $group.clusterDeployments */}} +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/acm/templates/provision/clusterpool.yaml b/acm/templates/provision/clusterpool.yaml index e2f9d3d1..d95905f7 100644 --- a/acm/templates/provision/clusterpool.yaml +++ b/acm/templates/provision/clusterpool.yaml @@ -1,17 +1,5 @@ {{- range .Values.clusterGroup.managedClusterGroups }} {{- $group := . }} -{{- if .clusterPools }}{{- /* We only create ManagedClusterSets if there are clusterPools defined */}} -apiVersion: cluster.open-cluster-management.io/v1beta1 -kind: ManagedClusterSet -metadata: - annotations: - cluster.open-cluster-management.io/submariner-broker-ns: {{ .name }}-broker - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - name: {{ .name }} -spec: - clusterSelector: - selectorType: LegacyClusterSetLabel ---- {{- range .clusterPools }} {{- $pool := . }} @@ -54,7 +42,7 @@ spec: runningCount: {{ $numClusters }} baseDomain: {{ .baseDomain }} installConfigSecretTemplateRef: - name: {{ $poolName }}-install-config + name: {{ $poolName }}-install-config imageSetRef: name: img{{ .openshiftVersion }}-multi-appsub pullSecretRef: @@ -91,5 +79,4 @@ spec: --- {{- end }}{{- /* range .range clusters */}} {{- end }}{{- /* range .clusterPools */}} -{{- end }}{{- /* if .clusterPools) */}} {{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/acm/templates/provision/managedclusterset.yaml b/acm/templates/provision/managedclusterset.yaml new file mode 100644 index 00000000..dce01f73 --- /dev/null +++ b/acm/templates/provision/managedclusterset.yaml @@ -0,0 +1,16 @@ +{{- range .Values.clusterGroup.managedClusterGroups }} +{{- if or .clusterPools .clusterDeployments }}{{- /* We only create ManagedClusterSets if there are clusterPools or clusterDeployments defined */}} +--- +apiVersion: cluster.open-cluster-management.io/v1beta2 +kind: ManagedClusterSet +metadata: + annotations: + cluster.open-cluster-management.io/submariner-broker-ns: {{ .name }}-broker + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + name: {{ .name }} +spec: + clusterSelector: + selectorType: LegacyClusterSetLabel + +{{- end }}{{- /* if .clusterPools) */}} +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/acm/templates/provision/secrets-aws.yaml b/acm/templates/provision/secrets-aws.yaml index 002c9247..a671638d 100644 --- a/acm/templates/provision/secrets-aws.yaml +++ b/acm/templates/provision/secrets-aws.yaml @@ -3,58 +3,82 @@ {{- range .clusterPools }} {{- $poolName := print .name "-" $group.name }} {{- if .platform.aws }} +--- +{{- template "externalsecret.aws.creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.aws.infra-creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} + +{{- end }}{{- /* if .platform.aws */}} +{{- end }}{{- /* range .clusterPools */}} + +{{- range .clusterDeployments }} +{{- $deploymentName := print .name "-" $group.name }} +{{- if .platform.aws }} +--- +{{- template "externalsecret.aws.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.aws.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} + +{{- end }}{{- /* if .platform.aws */}} +{{- end }}{{- /* range .clusterDeployments */}} + +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} + +{{- define "externalsecret.aws.creds" }} apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-creds + name: {{ .name }}-creds spec: dataFrom: - extract: # Expects entries called: aws_access_key_id and aws_secret_access_key - key: {{ default "secret/data/hub/aws" .awsKeyPath }} + key: {{ default "secret/data/hub/aws" .context.awsKeyPath }} refreshInterval: 24h0m0s secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-creds + name: {{ .name }}-creds creationPolicy: Owner template: type: Opaque ---- +{{- end}} + +{{- define "externalsecret.aws.infra-creds"}} # For use when manually creating clusters with ACM apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-infra-creds -spec: + name: {{ .name }}-infra-creds +spec: data: - secretKey: openshiftPullSecret remoteRef: - key: {{ default "secret/data/hub/openshiftPullSecret" .pullSecretKeyPath }} + key: {{ default "secret/data/hub/openshiftPullSecret" .context.pullSecretKeyPath }} property: content - secretKey: awsKeyId remoteRef: - key: {{ default "secret/data/hub/aws" .awsKeyPath }} + key: {{ default "secret/data/hub/aws" .context.awsKeyPath }} property: aws_access_key_id - secretKey: awsAccessKey remoteRef: - key: {{ default "secret/data/hub/aws" .awsKeyPath }} + key: {{ default "secret/data/hub/aws" .context.awsKeyPath }} property: aws_secret_access_key - secretKey: sshPublicKey remoteRef: - key: {{ default "secret/data/hub/publickey" .sshPublicKeyPath }} + key: {{ default "secret/data/hub/publickey" .context.sshPublicKeyPath }} property: content - secretKey: sshPrivateKey remoteRef: - key: {{ default "secret/data/hub/privatekey" .sshPrivateKeyPath }} + key: {{ default "secret/data/hub/privatekey" .context.sshPrivateKeyPath }} property: content refreshInterval: 24h0m0s - secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + secretStoreRef: + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-infra-creds + name: {{ .name }}-infra-creds creationPolicy: Owner template: type: Opaque @@ -63,7 +87,7 @@ spec: cluster.open-cluster-management.io/credentials: "" cluster.open-cluster-management.io/type: aws data: - baseDomain: "{{ .baseDomain }}" + baseDomain: "{{ .context.baseDomain }}" pullSecret: |- {{ "{{ .openshiftPullSecret | toString }}" }} aws_access_key_id: |- @@ -78,7 +102,4 @@ spec: httpsProxy: "" noProxy: "" additionalTrustBundle: "" ---- -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file +{{- end}} diff --git a/acm/templates/provision/secrets-azure.yaml b/acm/templates/provision/secrets-azure.yaml index 7fe6271b..21c9d482 100644 --- a/acm/templates/provision/secrets-azure.yaml +++ b/acm/templates/provision/secrets-azure.yaml @@ -3,58 +3,84 @@ {{- range .clusterPools }} {{- $poolName := print .name "-" $group.name }} {{- if .platform.azure }} +--- +{{- template "externalsecret.azure.creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.azure.infra-creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} + +--- +{{- end }}{{- /* if .platform.azure */}} +{{- end }}{{- /* range .clusterPools */}} + +{{- range .clusterDeployments }} +{{- $deploymentName := print .name "-" $group.name }} +{{- if .platform.azure }} +--- +{{- template "externalsecret.azure.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.azure.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} + + +{{- end }}{{- /* if .platform.azure */}} +{{- end }}{{- /* range .clusterPools */}} + +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} + +{{- define "externalsecret.azure.creds" }} apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-creds + name: {{ .name }}-creds spec: data: - secretKey: azureOsServicePrincipal remoteRef: - key: {{ default "secret/data/hub/azureOsServicePrincipal" .azureKeyPath }} + key: {{ default "secret/data/hub/azureOsServicePrincipal" .context.azureKeyPath }} property: content refreshInterval: 24h0m0s secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-creds + name: {{ .name }}-creds creationPolicy: Owner template: type: Opaque data: osServicePrincipal.json: |- {{ "{{ .azureOsServicePrincipal | toString }}" }} ---- +{{- end }} + +{{- define "externalsecret.azure.infra-creds"}} # For use when manually creating clusters with ACM apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-infra-creds -spec: + name: {{ .name }}-infra-creds +spec: data: - secretKey: openshiftPullSecret remoteRef: - key: {{ default "secret/data/hub/openshiftPullSecret" .pullSecretKeyPath }} + key: {{ default "secret/data/hub/openshiftPullSecret" .context.pullSecretKeyPath }} property: content - secretKey: sshPublicKey remoteRef: - key: {{ default "secret/data/hub/publickey" .sshPublicKeyPath }} + key: {{ default "secret/data/hub/publickey" .context.sshPublicKeyPath }} property: content - secretKey: sshPrivateKey remoteRef: - key: {{ default "secret/data/hub/privatekey" .sshPrivateKeyPath }} + key: {{ default "secret/data/hub/privatekey" .context.sshPrivateKeyPath }} property: content - secretKey: azureOsServicePrincipal remoteRef: - key: {{ default "secret/data/hub/azureOsServicePrincipal" .azureKeyPath }} + key: {{ default "secret/data/hub/azureOsServicePrincipal" .context.azureKeyPath }} property: content refreshInterval: 24h0m0s - secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + secretStoreRef: + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-infra-creds + name: {{ .name }}-infra-creds creationPolicy: Owner template: type: Opaque @@ -66,8 +92,8 @@ spec: cloudName: AzurePublicCloud osServicePrincipal.json: |- {{ "{{ .azureOsServicePrincipal | toString }}" }} - baseDomain: "{{ .baseDomain }}" - baseDomainResourceGroupName: "{{ .platform.azure.baseDomainResourceGroupName | toString }}" + baseDomain: "{{ .context.baseDomain }}" + baseDomainResourceGroupName: "{{ .context.platform.azure.baseDomainResourceGroupName | toString }}" pullSecret: |- {{ "{{ .openshiftPullSecret | toString }}" }} ssh-privatekey: |- @@ -78,7 +104,4 @@ spec: httpsProxy: "" noProxy: "" additionalTrustBundle: "" ---- -{{- end }} -{{- end }} {{- end }} diff --git a/acm/templates/provision/secrets-common.yaml b/acm/templates/provision/secrets-common.yaml index 21a03b73..474347c6 100644 --- a/acm/templates/provision/secrets-common.yaml +++ b/acm/templates/provision/secrets-common.yaml @@ -1,61 +1,86 @@ {{- range .Values.clusterGroup.managedClusterGroups }} {{- $group := . }} + {{- range .clusterPools }} {{- $poolName := print .name "-" $group.name }} +--- +{{- template "secret.install-config" (dict "name" $poolName "context" .) }} +--- +{{- template "externalsecret.pull-secret" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.ssh.private.key" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} +{{- end }}{{- /* range .clusterPools */}} + +{{- range .clusterDeployments }} +{{- $deploymentName := print .name "-" $group.name }} +--- +{{- template "secret.install-config" (dict "name" $deploymentName "context" .) }} +--- +{{- template "externalsecret.pull-secret" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.ssh.private.key" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- end }}{{- /* range .clusterDeplyments */}} + +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} + +{{- define "secret.install-config"}} apiVersion: v1 kind: Secret metadata: - name: {{ $poolName }}-install-config + name: {{ .name }}-install-config data: # Base64 encoding of install-config yaml - install-config.yaml: {{ include "cluster.install-config" . | b64enc }} + install-config.yaml: {{ include "cluster.install-config" .context | b64enc }} type: Opaque ---- +{{- end }} + +{{- define "externalsecret.pull-secret" }} apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-pull-secret -spec: + name: {{ .name }}-pull-secret +spec: data: - secretKey: openshiftPullSecret remoteRef: - key: {{ default "secret/data/hub/openshiftPullSecret" .pullSecretKeyPath }} + key: {{ default "secret/data/hub/openshiftPullSecret" .context.pullSecretKeyPath }} property: content refreshInterval: 24h0m0s secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-pull-secret + name: {{ .name }}-pull-secret creationPolicy: Owner template: type: kubernetes.io/dockerconfigjson data: .dockerconfigjson: |- {{ "{{ .openshiftPullSecret | toString }}" }} ---- +{{- end }} + + +{{- define "externalsecret.ssh.private.key" }} apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-ssh-private-key + name: {{ .name }}-ssh-private-key spec: data: - secretKey: sshPrivateKey remoteRef: - key: {{ default "secret/data/hub/privatekey" .sshPrivateKeyPath }} + key: {{ default "secret/data/hub/privatekey" .context.sshPrivateKeyPath }} property: content refreshInterval: 24h0m0s secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-ssh-private-key + name: {{ .name }}-ssh-private-key creationPolicy: Owner template: type: Opaque data: ssh-privatekey: |- {{ "{{ .sshPrivateKey | toString }}" }} ---- -{{- end }} {{- end }} diff --git a/acm/values.yaml b/acm/values.yaml index fb7cb03a..54c84a2e 100644 --- a/acm/values.yaml +++ b/acm/values.yaml @@ -21,14 +21,29 @@ clusterGroup: # testPool: # name: spoke # openshiftVersion: 4.10.18 -# provider: -# region: ap-southeast-2 -# baseDomain: blueprints.rhecoeng.com +# baseDomain: blueprints.rhecoeng.com +# platform: +# aws: +# region: ap-southeast-2 # clusters: # - spoke1 # labels: # - name: clusterGroup # value: region-one +# testRegionTwo: +# name: region-two +# clusterDeployments: +# myFirstCluster: +# name: mcluster1 +# openshiftVersion: 4.10.18 +# baseDomain: blueprints.rhecoeng.com +# platform: +# azure: +# baseDomainResourceGroupName: dojo-dns-zones +# region: eastus +# labels: +# - name: clusterGroup +# value: region-two secretStore: name: vault-backend diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index cf14bf26..4b6190ae 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -741,6 +741,12 @@ "$ref": "#/definitions/ClusterPools" } }, + "clusterDeployments": { + "type": "object", + "items": { + "$ref": "#/definitions/ClusterDeployments" + } + }, "clusterSelector": { "type": "object", "additionalProperties": true @@ -788,6 +794,32 @@ ], "title": "ClusterPools" }, + "ClusterDeployments": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "openshiftVersion": { + "type": "string" + }, + "baseDomain": { + "type": "string" + }, + "platform": { + "type": "object", + "$ref": "#/definitions/ClusterPoolsPlatform" + } + }, + "required": [ + "name", + "openshiftVersion", + "baseDomain", + "platform" + ], + "title": "ClusterDeployments" + }, "ClusterPoolsPlatform": { "type": "object", "additionalProperties": false, From f9bf1f7842343181ee95c68d1126aa41087f6ee6 Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 16 Apr 2024 18:46:24 -0400 Subject: [PATCH 029/222] test: regenerated tests after clusterdeployment commit Co-authored-by: Alejandro Villegas Signed-off-by: Tomer Figenblat --- tests/acm-normal.expected.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 1a3f6e72..e83a83a6 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -6,7 +6,7 @@ metadata: name: aws-ap-acm-provision-edge-install-config data: # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWFwJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAxCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDAKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTIKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWFwJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAxCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDAKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTIKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz type: Opaque --- # Source: acm/templates/provision/secrets-common.yaml @@ -16,7 +16,7 @@ metadata: name: azure-us-acm-provision-edge-install-config data: # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== type: Opaque --- # Source: acm/templates/policies/acm-hub-ca-policy.yaml @@ -79,7 +79,7 @@ spec: runningCount: 0 baseDomain: blueprints.rhecoeng.com installConfigSecretTemplateRef: - name: aws-ap-acm-provision-edge-install-config + name: aws-ap-acm-provision-edge-install-config imageSetRef: name: img4.10.18-multi-appsub pullSecretRef: @@ -109,7 +109,7 @@ spec: runningCount: 2 baseDomain: blueprints.rhecoeng.com installConfigSecretTemplateRef: - name: azure-us-acm-provision-edge-install-config + name: azure-us-acm-provision-edge-install-config imageSetRef: name: img4.10.18-multi-appsub pullSecretRef: @@ -147,7 +147,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-ap-acm-provision-edge-infra-creds -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -170,7 +170,7 @@ spec: key: secret/data/hub/privatekey property: content refreshInterval: 24h0m0s - secretStoreRef: + secretStoreRef: name: vault-backend kind: ClusterSecretStore target: @@ -229,7 +229,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: azure-us-acm-provision-edge-infra-creds -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -248,7 +248,7 @@ spec: key: secret/data/hub/azureOsServicePrincipal property: content refreshInterval: 24h0m0s - secretStoreRef: + secretStoreRef: name: vault-backend kind: ClusterSecretStore target: @@ -282,7 +282,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-ap-acm-provision-edge-pull-secret -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -330,7 +330,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: azure-us-acm-provision-edge-pull-secret -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -373,8 +373,8 @@ spec: ssh-privatekey: |- {{ .sshPrivateKey | toString }} --- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: cluster.open-cluster-management.io/v1beta1 +# Source: acm/templates/provision/managedclusterset.yaml +apiVersion: cluster.open-cluster-management.io/v1beta2 kind: ManagedClusterSet metadata: annotations: From aee51586f7a02366fada0032ebe74b89e15ce4c6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 17 Apr 2024 16:17:57 +0200 Subject: [PATCH 030/222] Support remote repoURL when previewing templates This allows us to have a remote repoURL + path kustomize combo and show the resulting templates in `make preview`. Tested with: web-terminal: name: web-terminal namespace: hello-world project: hub kustomize: true targetRevision: main repoURL: https://github.com/redhat-cop/gitops-catalog path: web-terminal/aggregate/overlays/default Closes: https://github.com/validatedpatterns/multicloud-gitops/issues/356 --- scripts/preview.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/preview.sh b/scripts/preview.sh index ac2cd5c8..b9839c51 100755 --- a/scripts/preview.sh +++ b/scripts/preview.sh @@ -96,6 +96,10 @@ done if [ $isKustomize == "true" ]; then kustomizePath=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) + repoURL=$(yq ".clusterGroup.applications.$APP.repoURL" values-$SITE.yaml) + if [[ $repoURL == http* ]] || [[ $repoURL == git@ ]]; then + kustomizePath="${repoURL}/${kustomizePath}" + fi cmd="oc kustomize ${kustomizePath}" eval "$cmd" else From 5b4e9038b1e9dca267137cccf5648b25c10c2665 Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 16 Apr 2024 20:03:57 -0400 Subject: [PATCH 031/222] test: updated test-cased and regeneated expectations Co-authored-by: Alejandro Villegas Signed-off-by: Tomer Figenblat --- examples/values-example.yaml | 23 +- tests/acm-normal.expected.yaml | 499 ++++++++++++++++++++++++ tests/clustergroup-normal.expected.yaml | 17 + 3 files changed, 536 insertions(+), 3 deletions(-) diff --git a/examples/values-example.yaml b/examples/values-example.yaml index 84682e20..b8b1dde9 100644 --- a/examples/values-example.yaml +++ b/examples/values-example.yaml @@ -15,7 +15,7 @@ clusterGroup: - /values/{{ .Values.global.clusterPlatform }}.yaml - /values/{{ .Values.global.clusterVersion }}.yaml - # + # # You can define namespaces using hashes and not as a list like so: # namespaces: # open-cluster-management: @@ -25,7 +25,7 @@ clusterGroup: # annotations: # openshift.io/cluster-monitoring: "true" # owner: "namespace owner" - # application-ci: + # application-ci: # You cannot mix list and hashes to define namespaces namespaces: - open-cluster-management: @@ -70,7 +70,7 @@ clusterGroup: name: openshift-pipelines-operator-rh csv: redhat-openshift-pipelines.v1.5.2 - # + # # You can define projects using hashes like so: # projects: # hub: @@ -159,9 +159,26 @@ clusterGroup: clusters: - Two - three + clusterDeployments: + myFirstCluster: + name: aws-cd-one-w-pool + openshiftVersion: 4.10.18 + baseDomain: blueprints.rhecoeng.com + platform: + aws: + region: ap-southeast-1 acmlabels: - name: clusterGroup value: region + - name: acm-provision-on-deploy + clusterDeployments: + mySecondCluster: + name: aws-cd-two-wo-pool + openshiftVersion: 4.10.18 + baseDomain: blueprints.rhecoeng.com + platform: + aws: + region: ap-southeast-3 - name: argo-edge hostedArgoSites: - name: perth diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index e83a83a6..1e63d2e7 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1,4 +1,16 @@ --- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: v1 +kind: Namespace +metadata: + name: aws-cd-one-w-pool-acm-provision-edge +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: v1 +kind: Namespace +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy +--- # Source: acm/templates/provision/secrets-common.yaml apiVersion: v1 kind: Secret @@ -19,6 +31,26 @@ data: install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== type: Opaque --- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: v1 +kind: Secret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-install-config +data: + # Base64 encoding of install-config yaml + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLW9uZS13LXBvb2wnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCmNvbXB1dGU6Ci0gaHlwZXJ0aHJlYWRpbmc6IEVuYWJsZWQKICBhcmNoaXRlY3R1cmU6IGFtZDY0CiAgbmFtZTogJ3dvcmtlcicKICByZXBsaWNhczogMwogIHBsYXRmb3JtOgogICAgYXdzOgogICAgICB0eXBlOiBtNS54bGFyZ2UKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTEKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz +type: Opaque +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: v1 +kind: Secret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config +data: + # Base64 encoding of install-config yaml + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLXR3by13by1wb29sJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhd3M6CiAgICByZWdpb246IGFwLXNvdXRoZWFzdC0zCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== +type: Opaque +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml # This pushes out the HUB's Certificate Authorities on to the imported clusters --- @@ -61,6 +93,60 @@ metadata: spec: clusterPoolName: azure-us-acm-provision-edge --- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: hive.openshift.io/v1 +kind: ClusterDeployment +metadata: + name: aws-cd-one-w-pool-acm-provision-edge + namespace: aws-cd-one-w-pool-acm-provision-edge + labels: + vendor: OpenShift +spec: + baseDomain: blueprints.rhecoeng.com + clusterName: aws-cd-one-w-pool-acm-provision-edge + installAttemptsLimit: 1 + platform: + aws: + credentialsSecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-creds + region: ap-southeast-1 + provisioning: + installConfigSecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-install-config + sshPrivateKeySecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key + imageSetRef: + name: img4.10.18-multi-appsub + pullSecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-pull-secret +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: hive.openshift.io/v1 +kind: ClusterDeployment +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy + labels: + vendor: OpenShift +spec: + baseDomain: blueprints.rhecoeng.com + clusterName: aws-cd-two-wo-pool-acm-provision-on-deploy + installAttemptsLimit: 1 + platform: + aws: + credentialsSecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds + region: ap-southeast-3 + provisioning: + installConfigSecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config + sshPrivateKeySecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key + imageSetRef: + name: img4.10.18-multi-appsub + pullSecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret +--- # Source: acm/templates/provision/clusterpool.yaml apiVersion: hive.openshift.io/v1 kind: ClusterPool @@ -199,6 +285,162 @@ spec: noProxy: "" additionalTrustBundle: "" --- +# Source: acm/templates/provision/secrets-aws.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-creds +spec: + dataFrom: + - extract: + # Expects entries called: aws_access_key_id and aws_secret_access_key + key: secret/data/hub/aws + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-creds + creationPolicy: Owner + template: + type: Opaque +--- +# Source: acm/templates/provision/secrets-aws.yaml +# For use when manually creating clusters with ACM +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-infra-creds +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + - secretKey: awsKeyId + remoteRef: + key: secret/data/hub/aws + property: aws_access_key_id + - secretKey: awsAccessKey + remoteRef: + key: secret/data/hub/aws + property: aws_secret_access_key + - secretKey: sshPublicKey + remoteRef: + key: secret/data/hub/publickey + property: content + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-infra-creds + creationPolicy: Owner + template: + type: Opaque + metadata: + labels: + cluster.open-cluster-management.io/credentials: "" + cluster.open-cluster-management.io/type: aws + data: + baseDomain: "blueprints.rhecoeng.com" + pullSecret: |- + {{ .openshiftPullSecret | toString }} + aws_access_key_id: |- + {{ .awsKeyId | toString }} + aws_secret_access_key: |- + {{ .awsAccessKey | toString }} + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} + ssh-publickey: |- + {{ .sshPublicKey | toString }} + httpProxy: "" + httpsProxy: "" + noProxy: "" + additionalTrustBundle: "" +--- +# Source: acm/templates/provision/secrets-aws.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds +spec: + dataFrom: + - extract: + # Expects entries called: aws_access_key_id and aws_secret_access_key + key: secret/data/hub/aws + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds + creationPolicy: Owner + template: + type: Opaque +--- +# Source: acm/templates/provision/secrets-aws.yaml +# For use when manually creating clusters with ACM +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + - secretKey: awsKeyId + remoteRef: + key: secret/data/hub/aws + property: aws_access_key_id + - secretKey: awsAccessKey + remoteRef: + key: secret/data/hub/aws + property: aws_secret_access_key + - secretKey: sshPublicKey + remoteRef: + key: secret/data/hub/publickey + property: content + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds + creationPolicy: Owner + template: + type: Opaque + metadata: + labels: + cluster.open-cluster-management.io/credentials: "" + cluster.open-cluster-management.io/type: aws + data: + baseDomain: "blueprints.rhecoeng.com" + pullSecret: |- + {{ .openshiftPullSecret | toString }} + aws_access_key_id: |- + {{ .awsKeyId | toString }} + aws_secret_access_key: |- + {{ .awsAccessKey | toString }} + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} + ssh-publickey: |- + {{ .sshPublicKey | toString }} + httpProxy: "" + httpsProxy: "" + noProxy: "" + additionalTrustBundle: "" +--- # Source: acm/templates/provision/secrets-azure.yaml apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret @@ -373,6 +615,124 @@ spec: ssh-privatekey: |- {{ .sshPrivateKey | toString }} --- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-pull-secret +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-pull-secret + creationPolicy: Owner + template: + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: |- + {{ .openshiftPullSecret | toString }} +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key +spec: + data: + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key + creationPolicy: Owner + template: + type: Opaque + data: + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret + creationPolicy: Owner + template: + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: |- + {{ .openshiftPullSecret | toString }} +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key +spec: + data: + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key + creationPolicy: Owner + template: + type: Opaque + data: + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: cluster.open-cluster-management.io/v1 +kind: ManagedCluster +metadata: + labels: + cluster.open-cluster-management.io/clusterset: acm-provision-edge + clusterGroup: region + name: aws-cd-one-w-pool-acm-provision-edge +spec: + hubAcceptsClient: true +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: cluster.open-cluster-management.io/v1 +kind: ManagedCluster +metadata: + labels: + cluster.open-cluster-management.io/clusterset: acm-provision-on-deploy + clusterGroup: acm-provision-on-deploy + name: aws-cd-two-wo-pool-acm-provision-on-deploy +spec: + hubAcceptsClient: true +--- # Source: acm/templates/provision/managedclusterset.yaml apiVersion: cluster.open-cluster-management.io/v1beta2 kind: ManagedClusterSet @@ -385,6 +745,18 @@ spec: clusterSelector: selectorType: LegacyClusterSetLabel --- +# Source: acm/templates/provision/managedclusterset.yaml +apiVersion: cluster.open-cluster-management.io/v1beta2 +kind: ManagedClusterSet +metadata: + annotations: + cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-on-deploy-broker + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + name: acm-provision-on-deploy +spec: + clusterSelector: + selectorType: LegacyClusterSetLabel +--- # Source: acm/templates/multiclusterhub.yaml apiVersion: operator.open-cluster-management.io/v1 kind: MultiClusterHub @@ -444,6 +816,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/application-policies.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: acm-provision-on-deploy-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: acm-provision-on-deploy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: acm-provision-on-deploy-clustergroup-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -508,6 +896,21 @@ spec: matchLabels: clusterGroup: region --- +# Source: acm/templates/policies/application-policies.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: acm-provision-on-deploy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchLabels: + clusterGroup: acm-provision-on-deploy +--- # Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -763,6 +1166,102 @@ spec: jsonPointers: - /status --- +# Source: acm/templates/policies/application-policies.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: acm-provision-on-deploy-clustergroup-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: acm-provision-on-deploy-clustergroup-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1alpha1 + kind: Application + metadata: + name: mypattern-acm-provision-on-deploy + namespace: openshift-gitops + finalizers: + - resources-finalizer.argocd.argoproj.io/foreground + spec: + project: default + source: + repoURL: https://github.com/pattern-clone/mypattern + targetRevision: main + path: common/clustergroup + helm: + ignoreMissingValueFiles: true + valueFiles: + - "/values-global.yaml" + - "/values-acm-provision-on-deploy.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-on-deploy.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + parameters: + - name: global.repoURL + value: https://github.com/pattern-clone/mypattern + - name: global.targetRevision + value: main + - name: global.namespace + value: $ARGOCD_APP_NAMESPACE + - name: global.pattern + value: mypattern + - name: global.hubClusterDomain + value: apps.hub.example.com + - name: global.localClusterDomain + value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' + # Requires ACM 2.6 or higher + - name: global.clusterDomain + value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' + # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) + - name: global.clusterVersion + value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' + - name: global.localClusterName + value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' + - name: global.clusterPlatform + value: aws + - name: clusterGroup.name + value: acm-provision-on-deploy + - name: global.experimentalCapabilities + value: + destination: + server: https://kubernetes.default.svc + namespace: mypattern-acm-provision-on-deploy + syncPolicy: + automated: + prune: false + selfHeal: true + retry: + limit: 20 + ignoreDifferences: + - group: apps + kind: Deployment + jsonPointers: + - /spec/replicas + - group: route.openshift.io + kind: Route + jsonPointers: + - /status +--- # Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 8d3d4d51..e449dd9c 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -160,6 +160,14 @@ data: - acmlabels: - name: clusterGroup value: region + clusterDeployments: + myFirstCluster: + baseDomain: blueprints.rhecoeng.com + name: aws-cd-one-w-pool + openshiftVersion: 4.10.18 + platform: + aws: + region: ap-southeast-1 clusterPools: exampleAWSPool: baseDomain: blueprints.rhecoeng.com @@ -192,6 +200,15 @@ data: value: "false" name: acm-provision-edge targetRevision: main + - clusterDeployments: + mySecondCluster: + baseDomain: blueprints.rhecoeng.com + name: aws-cd-two-wo-pool + openshiftVersion: 4.10.18 + platform: + aws: + region: ap-southeast-3 + name: acm-provision-on-deploy - helmOverrides: - name: clusterGroup.isHubCluster value: "false" From 890ac2e46e952446d9737105d97e52766603d638 Mon Sep 17 00:00:00 2001 From: Wade Bee Date: Wed, 17 Apr 2024 14:25:16 -0400 Subject: [PATCH 032/222] Moved CLUSTERGROUP declaration to restore make preview-% functionality --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c6c7539c..b15f4beb 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ NAME ?= $(shell basename "`pwd`") +CLUSTERGROUP ?= $(shell yq ".main.clusterGroupName" values-global.yaml) + ifneq ($(origin TARGET_SITE), undefined) TARGET_SITE_OPT=--set main.clusterGroupName=$(TARGET_SITE) endif @@ -60,7 +62,6 @@ preview-all: ## (EXPERIMENTAL) Previews all applications on hub and managed clus @common/scripts/preview-all.sh $(TARGET_REPO) $(TARGET_BRANCH) preview-%: - CLUSTERGROUP?=$(shell yq ".main.clusterGroupName" values-global.yaml) @common/scripts/preview.sh $(CLUSTERGROUP) $* $(TARGET_REPO) $(TARGET_BRANCH) .PHONY: operator-deploy From e27624cbf1f5e0664350d37bc90176d3de63fa59 Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Wed, 17 Apr 2024 15:43:48 -0600 Subject: [PATCH 033/222] Namespace argocd.argoproj.io/managed-by label issue - Fixed issue in common/clustergroup/templates/_helpers.tpl to render correct label --- clustergroup/templates/_helpers.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index 44b2d073..9054f3bd 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -164,7 +164,7 @@ metadata: name: {{ $k }} {{- if ne $v nil }} labels: - argocd.argoproj.io/managed-by: {{ $patternName }}-{{ .clusterGroupName }} + argocd.argoproj.io/managed-by: {{ $patternName }}-{{ $clusterGroupName }} {{- if $v.labels }} {{- range $key, $value := $v.labels }} {{- /* We loop here even though the map has always just one key */}} {{ $key }}: {{ $value | default "" | quote }} From 13ee338d128fde8a7026e4c09de3eee13fe77ffa Mon Sep 17 00:00:00 2001 From: Wade Bee Date: Wed, 17 Apr 2024 17:59:12 -0400 Subject: [PATCH 034/222] Fixed indenting and duplicate entries in application-policies.yaml This corrects Argo error: Failed to load target state: failed to generate manifest for source 1 of 1: rpc error: code = Unknown desc = Manifest generation error (cached): `helm template . --name-template acm --namespace open-cluster-management --kube-version 1.25 --set global.privateRepo=false --set global.experimentalCapabilities=initcontainers --set global.repoURL=https://github.myrepo.com/EnterpriseKubernetes/multicloud-gitops.git --set global.clusterDomain=mydomain.azure.us --set global.clusterPlatform=Azure --set global.hubClusterDomain=mydomain.azure.us --set global.localClusterDomain=mydomain.azure.us --set global.targetRevision=prod --set global.namespace=open-cluster-management --set global.pattern=ekho --set global.clusterVersion=4.12 --values /values-global.yaml --values /values-hub.yaml --include-crds` failed exit status 1: Error: YAML parse error on acm/templates/policies/application-policies.yaml: error converting YAML to JSON: yaml: line 50: did not find expected key Use --debug flag to render out invalid YAML Also corrects mapping error warning on make preview-acm --- acm/templates/policies/application-policies.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 925915c8..94c624b4 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -44,13 +44,10 @@ spec: helm: ignoreMissingValueFiles: true valueFiles: - {{- include "acm.app.policies.valuefiles" . | nindent 24 }} + {{- include "acm.app.policies.valuefiles" . | nindent 22 }} {{- range $valueFile := $.Values.global.extraValueFiles }} - {{ $valueFile | quote }} {{- end }} - {{- range $valueFile := .extraValueFiles }} - - {{ $valueFile | quote }} - {{- end }} parameters: - name: global.repoURL value: {{ $.Values.global.repoURL }} From 50b2f5554d7bf503f4e9e008935f9664c0ebf915 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 18 Apr 2024 08:17:27 +0200 Subject: [PATCH 035/222] Add main.experimentalCapabilities to values.schema.json This way it can be set straight from a values-*.yaml file Tested on MCG. --- clustergroup/values.schema.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index cf14bf26..071805fe 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -65,6 +65,10 @@ "clusterGroupName": { "type": "string" }, + "experimentalCapabilities": { + "type": "string", + "description": "String to enable certain experimental capabilities in the operator and the framework." + }, "git": { "type": "object", "additionalProperties": false, From 866cd995c6e801e29a97bf77ed63b1b16d7c4dff Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 18 Apr 2024 08:22:02 +0200 Subject: [PATCH 036/222] Release clustergroup v0.8.4 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 367cea35..c8ba873f 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.3 +version: 0.8.4 From 739a63b1ac0f1efadbe6db25632c8b710879664c Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 18 Apr 2024 12:41:55 +0200 Subject: [PATCH 037/222] Move the CLUSTERGROUP env variable for previews inside its section This way the code is a bit less confusing and it's more obvious when/where CLUSTERGROUP is used. make preview-% still keeps working as usual and you can override things via `make CLUSTERGROUP=group-one preview-hello-world` Gotta love Makefile's idiosyncrasies around per-target variables --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b15f4beb..7882a9ce 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ NAME ?= $(shell basename "`pwd`") -CLUSTERGROUP ?= $(shell yq ".main.clusterGroupName" values-global.yaml) ifneq ($(origin TARGET_SITE), undefined) TARGET_SITE_OPT=--set main.clusterGroupName=$(TARGET_SITE) @@ -62,6 +61,7 @@ preview-all: ## (EXPERIMENTAL) Previews all applications on hub and managed clus @common/scripts/preview-all.sh $(TARGET_REPO) $(TARGET_BRANCH) preview-%: + $(eval CLUSTERGROUP ?= $(shell yq ".main.clusterGroupName" values-global.yaml)) @common/scripts/preview.sh $(CLUSTERGROUP) $* $(TARGET_REPO) $(TARGET_BRANCH) .PHONY: operator-deploy From 65eab76b505dc46e21746e11d97ecd4207c597fa Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 18 Apr 2024 15:31:52 +0200 Subject: [PATCH 038/222] Fix up tests after upstream PR merge --- tests/acm-industrial-edge-hub.expected.yaml | 16 +++++----- tests/acm-medical-diagnosis-hub.expected.yaml | 16 +++++----- tests/acm-normal.expected.yaml | 32 +++++++++---------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index a912f0cd..b44e051d 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -215,14 +215,14 @@ spec: helm: ignoreMissingValueFiles: true valueFiles: - - "/values-global.yaml" - - "/values-factory.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-factory.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-factory.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-factory.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 3ac5fe17..b98682af 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -206,14 +206,14 @@ spec: helm: ignoreMissingValueFiles: true valueFiles: - - "/values-global.yaml" - - "/values-region-one.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-region-one.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-region-one.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-region-one.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 1a3f6e72..ee3f05f6 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -609,14 +609,14 @@ spec: helm: ignoreMissingValueFiles: true valueFiles: - - "/values-global.yaml" - - "/values-acm-edge.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-edge.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-acm-edge.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-edge.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern @@ -707,14 +707,14 @@ spec: helm: ignoreMissingValueFiles: true valueFiles: - - "/values-global.yaml" - - "/values-acm-provision-edge.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-edge.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-acm-provision-edge.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-edge.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern From 444016b931b25915ea892d52dad7c6851ae114e1 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 18 Apr 2024 15:33:09 +0200 Subject: [PATCH 039/222] Drop old comments --- acm/templates/policies/application-policies.yaml | 2 -- tests/acm-industrial-edge-hub.expected.yaml | 2 -- tests/acm-medical-diagnosis-hub.expected.yaml | 2 -- tests/acm-normal.expected.yaml | 4 ---- 4 files changed, 10 deletions(-) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 94c624b4..131f4f3e 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -61,10 +61,8 @@ spec: value: {{ $.Values.global.hubClusterDomain }} - name: global.localClusterDomain value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}` }}' - # Requires ACM 2.6 or higher - name: global.clusterDomain value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}` }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - name: global.clusterVersion value: '{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}' - name: global.localClusterName diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index b44e051d..21a1c30d 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -236,10 +236,8 @@ spec: value: apps.hub.example.com - name: global.localClusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - name: global.clusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - name: global.clusterVersion value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - name: global.localClusterName diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index b98682af..40df35e2 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -227,10 +227,8 @@ spec: value: apps.hub.example.com - name: global.localClusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - name: global.clusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - name: global.clusterVersion value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - name: global.localClusterName diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index ee3f05f6..20a38d52 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -630,10 +630,8 @@ spec: value: apps.hub.example.com - name: global.localClusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - name: global.clusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - name: global.clusterVersion value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - name: global.localClusterName @@ -728,10 +726,8 @@ spec: value: apps.hub.example.com - name: global.localClusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - name: global.clusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - name: global.clusterVersion value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - name: global.localClusterName From 0283fc2fba0c9c97cbd358b44482f33db06057fd Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Thu, 18 Apr 2024 07:57:29 -0600 Subject: [PATCH 040/222] bug: Fix to generate OperatorGroup definition when namespaces definition has labels - Added condition to check if operatorGroup key exists {{- if or $v.operatorGroup (not (hasKey $v "operatorGroup")) }} - Default behavior is that we generate an OperatorGroup for a Namespace definition. --- clustergroup/templates/_helpers.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index 9054f3bd..04da642e 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -195,7 +195,7 @@ spec: {{- if or (empty $operatorgroupExcludes) (not (has . $operatorgroupExcludes)) }} {{- range $k, $v := $ns }}{{- /* We loop here even though the map has always just one key */}} {{- if $v }} - {{- if $v.operatorGroup }}{{- /* Checks if the user sets operatorGroup: false */}} + {{- if or $v.operatorGroup (not (hasKey $v "operatorGroup")) }}{{- /* Checks if the user sets operatorGroup: false */}} apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: From c35d1244b92245600c11743f29015c9b4bdef6e7 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 18 Apr 2024 21:09:07 +0200 Subject: [PATCH 041/222] Try fallbacks for /etc/pki when it does not exist --- scripts/pattern-util.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 0f865e0a..f7be58c2 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -48,6 +48,16 @@ if [ -n "$KUBECONFIG" ]; then exit 1 fi fi + +# Use /etc/pki by default and try a couple of fallbacks if it does not exist +if [ -d /etc/pki ]; then + PKI_HOST_MOUNT="/etc/pki" +elif [ -d /etc/ssl ]; then + PKI_HOST_MOUNT="/etc/ssl" +else + PKI_HOST_MOUNT="/usr/share/ca-certificates" +fi + # Copy Kubeconfig from current environment. The utilities will pick up ~/.kube/config if set so it's not mandatory # $HOME is mounted as itself for any files that are referenced with absolute paths # $HOME is mounted to /root because the UID in the container is 0 and that's where SSH looks for credentials @@ -57,7 +67,7 @@ podman run -it --rm --pull=newer \ -e EXTRA_HELM_OPTS \ -e EXTRA_PLAYBOOK_OPTS \ -e KUBECONFIG \ - -v /etc/pki:/etc/pki:ro \ + -v "${PKI_HOST_MOUNT}":/etc/pki:ro \ -v "${HOME}":"${HOME}" \ -v "${HOME}":/pattern-home \ ${PODMAN_ARGS} \ From ae1227458bb3b3414bea68abb030c6d5a2178c18 Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Fri, 19 Apr 2024 09:08:29 -0600 Subject: [PATCH 042/222] Fix for multiple OperatorGroup rendering - Fixed issue with rendering multiple OperatorGroup. Added the beginning (---) to signal document start. - Updated the applications.yaml to include beginning (---) to signal document start. --- clustergroup/templates/_helpers.tpl | 2 ++ clustergroup/templates/core/operatorgroup.yaml | 2 ++ clustergroup/templates/plumbing/applications.yaml | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index 04da642e..5001a06e 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -196,6 +196,7 @@ spec: {{- range $k, $v := $ns }}{{- /* We loop here even though the map has always just one key */}} {{- if $v }} {{- if or $v.operatorGroup (not (hasKey $v "operatorGroup")) }}{{- /* Checks if the user sets operatorGroup: false */}} +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -212,6 +213,7 @@ spec: {{- end }}{{- /* End of if hasKey $v "targetNamespaces" */}} {{- end }}{{- /* End if $v.operatorGroup */}} {{- else }}{{- /* else if $v == nil */}} +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: diff --git a/clustergroup/templates/core/operatorgroup.yaml b/clustergroup/templates/core/operatorgroup.yaml index 17aa966b..4d8c3014 100644 --- a/clustergroup/templates/core/operatorgroup.yaml +++ b/clustergroup/templates/core/operatorgroup.yaml @@ -15,6 +15,7 @@ {{- if kindIs "map" $ns }} {{- range $k, $v := $ns }}{{- /* We loop here even though the map has always just one key */}} {{- if $v.operatorGroup }}{{- /* Checks if the user sets operatorGroup: false */}} +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -32,6 +33,7 @@ spec: {{- end }}{{- /* range $k, $v := $ns */}} {{- end }}{{- /* End of if operatorGroup */}} {{- else if kindIs "string" $ns }} +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: diff --git a/clustergroup/templates/plumbing/applications.yaml b/clustergroup/templates/plumbing/applications.yaml index dbfefa8f..29db6f39 100644 --- a/clustergroup/templates/plumbing/applications.yaml +++ b/clustergroup/templates/plumbing/applications.yaml @@ -40,7 +40,7 @@ spec: limit: {{ default 20 $.Values.global.options.applicationRetryLimit }} {{- end }} {{- if .ignoreDifferences }} - ignoreDifferences: {{ .ignoreDifferences | toPrettyJson }} + ignoreDifferences: {{ .ignoreDifferences | toPrettyJson | nindent 2 }} {{- end }} source: repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} @@ -119,6 +119,7 @@ spec: server: {{ coalesce .destinationServer "https://kubernetes.default.svc" }} namespace: {{ coalesce .destinationNamespace .namespace $namespace }} {{- else }} +--- apiVersion: argoproj.io/v1alpha1 kind: Application metadata: @@ -280,7 +281,6 @@ spec: retry: limit: {{ default 20 $.Values.global.applicationRetryLimit }} {{- end }}{{- /* .syncPolicy */}} ---- {{- end }}{{- /* if or (.generators) (.generatorFile) (.useGeneratorValues) (.destinationServer) (.destinationNamespace) */}} {{- end }}{{- /* range .Values.clusterGroup.applications */}} {{- end }}{{- /* if not (eq .Values.enabled "core") */}} From 6ed1a054c4455a7da3470b290368fb1df354740c Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Fri, 19 Apr 2024 09:17:03 -0600 Subject: [PATCH 043/222] Updated tests for CI --- tests/acm-industrial-edge-hub.expected.yaml | 16 +++++----- tests/acm-medical-diagnosis-hub.expected.yaml | 16 +++++----- tests/acm-normal.expected.yaml | 32 +++++++++---------- ...roup-industrial-edge-factory.expected.yaml | 2 ++ ...tergroup-industrial-edge-hub.expected.yaml | 7 ++++ ...rgroup-medical-diagnosis-hub.expected.yaml | 8 +++++ tests/clustergroup-normal.expected.yaml | 7 +++- 7 files changed, 55 insertions(+), 33 deletions(-) diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index a912f0cd..b44e051d 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -215,14 +215,14 @@ spec: helm: ignoreMissingValueFiles: true valueFiles: - - "/values-global.yaml" - - "/values-factory.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-factory.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-factory.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-factory.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 3ac5fe17..b98682af 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -206,14 +206,14 @@ spec: helm: ignoreMissingValueFiles: true valueFiles: - - "/values-global.yaml" - - "/values-region-one.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-region-one.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-region-one.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-region-one.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 1a3f6e72..ee3f05f6 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -609,14 +609,14 @@ spec: helm: ignoreMissingValueFiles: true valueFiles: - - "/values-global.yaml" - - "/values-acm-edge.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-edge.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-acm-edge.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-edge.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern @@ -707,14 +707,14 @@ spec: helm: ignoreMissingValueFiles: true valueFiles: - - "/values-global.yaml" - - "/values-acm-provision-edge.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-edge.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-acm-provision-edge.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-edge.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index da521518..84d4eaa6 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -716,6 +716,7 @@ spec: - manuela-stormshift-line-dashboard --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -726,6 +727,7 @@ spec: - manuela-stormshift-machine-sensor --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index f84bbebb..d8158428 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -1434,6 +1434,7 @@ spec: - golang-external-secrets --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1444,6 +1445,7 @@ spec: - external-secrets --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1454,6 +1456,7 @@ spec: - open-cluster-management --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1464,6 +1467,7 @@ spec: - manuela-tst-all --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1474,6 +1478,7 @@ spec: - manuela-ci --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1484,6 +1489,7 @@ spec: - manuela-data-lake --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1494,6 +1500,7 @@ spec: - staging --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 9effcbab..4449986d 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -1581,6 +1581,7 @@ spec: - open-cluster-management --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1591,6 +1592,7 @@ spec: - openshift-serverless --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1601,6 +1603,7 @@ spec: - opendatahub --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1611,6 +1614,7 @@ spec: - openshift-storage --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1621,6 +1625,7 @@ spec: - xraylab-1 --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1631,6 +1636,7 @@ spec: - knative-serving --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1641,6 +1647,7 @@ spec: - staging --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1651,6 +1658,7 @@ spec: - vault --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 8d3d4d51..0cb1cc33 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -601,6 +601,9 @@ spec: name: helm-values-configmap-example restartPolicy: Never --- +# Source: clustergroup/templates/core/operatorgroup.yaml +--- +--- # Source: clustergroup/templates/core/subscriptions.yaml --- --- @@ -1135,6 +1138,7 @@ spec: text: 'Example ArgoCD' --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1146,6 +1150,7 @@ spec: - other-namespace --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1155,6 +1160,7 @@ spec: targetNamespaces: --- # Source: clustergroup/templates/core/operatorgroup.yaml +--- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: @@ -1165,7 +1171,6 @@ spec: - include-ci --- # Source: clustergroup/templates/core/operatorgroup.yaml ---- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: From 74a1f10bdd28ca042bfa15b1a73d973d22faa9f1 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 22 Apr 2024 12:18:36 +0200 Subject: [PATCH 044/222] Update ESO to 0.9.16 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.9.14.tgz | Bin 99176 -> 0 bytes .../charts/external-secrets-0.9.16.tgz | Bin 0 -> 102068 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 414 +++++++++++++++--- ...-secrets-industrial-edge-hub.expected.yaml | 414 +++++++++++++++--- ...ecrets-medical-diagnosis-hub.expected.yaml | 414 +++++++++++++++--- ...olang-external-secrets-naked.expected.yaml | 414 +++++++++++++++--- ...lang-external-secrets-normal.expected.yaml | 414 +++++++++++++++--- 9 files changed, 1824 insertions(+), 254 deletions(-) delete mode 100644 golang-external-secrets/charts/external-secrets-0.9.14.tgz create mode 100644 golang-external-secrets/charts/external-secrets-0.9.16.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 6e2f5b00..961f3b29 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.0.3 dependencies: - name: external-secrets - version: "0.9.14" + version: "0.9.16" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.9.14.tgz b/golang-external-secrets/charts/external-secrets-0.9.14.tgz deleted file mode 100644 index b75ffc1039b538b531ed211a0d76dc056de4502a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99176 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⁡Ve)YG||}Hk5Q1YGH8~ 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 J1K>vh_&-eMZIl22 diff --git a/golang-external-secrets/charts/external-secrets-0.9.16.tgz b/golang-external-secrets/charts/external-secrets-0.9.16.tgz new file mode 100644 index 0000000000000000000000000000000000000000..ca268d8459d75ca2b82392618d1bda98327bb264 GIT binary patch literal 102068 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 hT0^`F@P)29wf)lGg Date: Mon, 22 Apr 2024 13:33:53 +0200 Subject: [PATCH 045/222] Updated vault-helm to v0.28.0 --- hashicorp-vault/Chart.yaml | 2 +- hashicorp-vault/charts/vault-0.27.0.tgz | Bin 49088 -> 0 bytes hashicorp-vault/charts/vault-0.28.0.tgz | Bin 0 -> 49079 bytes hashicorp-vault/values.yaml | 2 +- ...ault-industrial-edge-factory.expected.yaml | 22 ++++++++++-------- ...rp-vault-industrial-edge-hub.expected.yaml | 22 ++++++++++-------- ...-vault-medical-diagnosis-hub.expected.yaml | 22 ++++++++++-------- tests/hashicorp-vault-naked.expected.yaml | 22 ++++++++++-------- tests/hashicorp-vault-normal.expected.yaml | 22 ++++++++++-------- 9 files changed, 62 insertions(+), 52 deletions(-) delete mode 100644 hashicorp-vault/charts/vault-0.27.0.tgz create mode 100644 hashicorp-vault/charts/vault-0.28.0.tgz diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index b9a20124..e1577595 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -6,5 +6,5 @@ name: hashicorp-vault version: 0.0.1 dependencies: - name: vault - version: "0.27.0" + version: "0.28.0" repository: "https://helm.releases.hashicorp.com" diff --git a/hashicorp-vault/charts/vault-0.27.0.tgz b/hashicorp-vault/charts/vault-0.27.0.tgz deleted file mode 100644 index 24a07991517b476c1391b305d0953e9e231a030c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49088 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
q0j)i=a#pu1jU+b_58*02a$>ktMv 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 literal 0 HcmV?d00001 diff --git a/golang-external-secrets/values.yaml b/golang-external-secrets/values.yaml index 8d30c3df..e3d14148 100644 --- a/golang-external-secrets/values.yaml +++ b/golang-external-secrets/values.yaml @@ -37,10 +37,10 @@ clusterGroup: external-secrets: image: - tag: v0.9.16-ubi + tag: v0.9.18-ubi webhook: image: - tag: v0.9.16-ubi + tag: v0.9.18-ubi certController: image: - tag: v0.9.16-ubi + tag: v0.9.18-ubi diff --git a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml index f0969200..712ec247 100644 --- a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml b/tests/golang-external-secrets-industrial-edge-hub.expected.yaml index 0ecbf649..08528096 100644 --- a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml b/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml index 0ecbf649..08528096 100644 --- a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml +++ b/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-naked.expected.yaml b/tests/golang-external-secrets-naked.expected.yaml index 55750256..c4f6c22f 100644 --- a/tests/golang-external-secrets-naked.expected.yaml +++ b/tests/golang-external-secrets-naked.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-normal.expected.yaml b/tests/golang-external-secrets-normal.expected.yaml index 0ecbf649..08528096 100644 --- a/tests/golang-external-secrets-normal.expected.yaml +++ b/tests/golang-external-secrets-normal.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook From 7d147b241dfa3b9feaa449eef23a3df8b037454f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 17 May 2024 12:28:40 +0200 Subject: [PATCH 072/222] Update vault to 1.16.2 --- hashicorp-vault/values.yaml | 2 +- tests/hashicorp-vault-industrial-edge-factory.expected.yaml | 4 ++-- tests/hashicorp-vault-industrial-edge-hub.expected.yaml | 4 ++-- tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml | 4 ++-- tests/hashicorp-vault-naked.expected.yaml | 4 ++-- tests/hashicorp-vault-normal.expected.yaml | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/hashicorp-vault/values.yaml b/hashicorp-vault/values.yaml index fa73a060..691f7094 100644 --- a/hashicorp-vault/values.yaml +++ b/hashicorp-vault/values.yaml @@ -48,4 +48,4 @@ vault: termination: "reencrypt" image: repository: "registry.connect.redhat.com/hashicorp/vault" - tag: "1.16.1-ubi" + tag: "1.16.2-ubi" diff --git a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml index 74212ee2..8156e2af 100644 --- a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml index 74212ee2..8156e2af 100644 --- a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml index 74212ee2..8156e2af 100644 --- a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-naked.expected.yaml b/tests/hashicorp-vault-naked.expected.yaml index 1fe2cd90..8727ef0e 100644 --- a/tests/hashicorp-vault-naked.expected.yaml +++ b/tests/hashicorp-vault-naked.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-normal.expected.yaml b/tests/hashicorp-vault-normal.expected.yaml index 74212ee2..8156e2af 100644 --- a/tests/hashicorp-vault-normal.expected.yaml +++ b/tests/hashicorp-vault-normal.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR From 4eeb69ba01e2227d060946d9a8632c36d2d8b3de Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Fri, 17 May 2024 10:24:44 -0600 Subject: [PATCH 073/222] Feat: Followup to definition of extraParameters under the main section of a values file. - The operator adds these extraParameters to the extraParametersNested section as key/value pairs in the Cluster Wide ArgoCD Application created by the Validated Patterns operator. - This update will add the user defined extra parameters on the ArgoCD Applications on the Spoke Clusters. efinition of extraParameters under the main --- .../policies/application-policies.yaml | 9 +++++++ .../templates/plumbing/applications.yaml | 10 +++++++ tests/acm-industrial-edge-hub.expected.yaml | 2 ++ tests/acm-medical-diagnosis-hub.expected.yaml | 2 ++ tests/acm-normal.expected.yaml | 4 +++ ...roup-industrial-edge-factory.expected.yaml | 2 ++ ...tergroup-industrial-edge-hub.expected.yaml | 14 ++++++++++ ...rgroup-medical-diagnosis-hub.expected.yaml | 26 +++++++++++++++++++ tests/clustergroup-normal.expected.yaml | 4 +++ 9 files changed, 73 insertions(+) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 0194d6bb..2a815913 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -43,6 +43,11 @@ spec: path: {{ default "common/clustergroup" .path }} helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: + {{- range $k, $v := $.Values.extraParametersNested }} + {{ $k }}: {{ printf "%s" $v | quote }} + {{- end }} valueFiles: {{- include "acm.app.policies.valuefiles" . | nindent 22 }} {{- range $valueFile := .extraValueFiles }} @@ -73,6 +78,10 @@ spec: value: {{ $group.name }} - name: global.experimentalCapabilities value: {{ $.Values.global.experimentalCapabilities }} + {{- range $k, $v := $.Values.extraParametersNested }} + - name: {{ $k }} + value: {{ printf "%s" $v | quote }} + {{- end }} {{- range .helmOverrides }} - name: {{ .name }} value: {{ .value | quote }} diff --git a/clustergroup/templates/plumbing/applications.yaml b/clustergroup/templates/plumbing/applications.yaml index 29db6f39..870babe3 100644 --- a/clustergroup/templates/plumbing/applications.yaml +++ b/clustergroup/templates/plumbing/applications.yaml @@ -149,6 +149,11 @@ spec: {{- else }} helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: + {{- range $k, $v := $.Values.extraParametersNested }} + {{ $k }}: {{ printf "%s" $v | quote }} + {{- end }} valueFiles: {{- include "clustergroup.app.globalvalues.prefixedvaluefiles" $ | nindent 8 }} {{- range $valueFile := $.Values.clusterGroup.sharedValueFiles }} @@ -216,6 +221,11 @@ spec: {{- else if not .kustomize }} helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: + {{- range $k, $v := $.Values.extraParametersNested }} + {{ $k }}: {{ printf "%s" $v | quote }} + {{- end }} valueFiles: {{- include "clustergroup.app.globalvalues.valuefiles" $ | nindent 6 }} {{- range $valueFile := $.Values.clusterGroup.sharedValueFiles }} diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 453e8a9e..eb1df26f 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -214,6 +214,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-factory.yaml" diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 8b50de7a..6a99a29c 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -205,6 +205,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-region-one.yaml" diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 66f1c590..d29937be 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -608,6 +608,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-acm-edge.yaml" @@ -704,6 +706,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-acm-provision-edge.yaml" diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index c3eabd83..356b7e7e 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -559,6 +559,8 @@ spec: path: charts/datacenter/opendatahub helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-factory.yaml" diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 393e530c..3291aeb2 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -857,6 +857,8 @@ spec: path: common/acm helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -922,6 +924,8 @@ spec: path: charts/datacenter/opendatahub helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -978,6 +982,8 @@ spec: path: charts/datacenter/pipelines helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1034,6 +1040,8 @@ spec: path: charts/datacenter/manuela-data-lake helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1120,6 +1128,8 @@ spec: path: charts/datacenter/external-secrets helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1176,6 +1186,8 @@ spec: path: common/golang-external-secrets helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1259,6 +1271,8 @@ spec: chart: vault helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index f4933c53..6e300fc3 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -742,6 +742,8 @@ spec: path: common/golang-external-secrets helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -798,6 +800,8 @@ spec: path: charts/all/kafdrop helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -854,6 +858,8 @@ spec: path: charts/all/kafka helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -910,6 +916,8 @@ spec: path: charts/all/opendatahub helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -966,6 +974,8 @@ spec: path: charts/all/openshift-data-foundations helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1022,6 +1032,8 @@ spec: path: charts/all/openshift-serverless helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1078,6 +1090,8 @@ spec: path: charts/all/medical-diagnosis/service-account helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1134,6 +1148,8 @@ spec: chart: vault helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1208,6 +1224,8 @@ spec: path: charts/all/medical-diagnosis/database helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1264,6 +1282,8 @@ spec: path: charts/all/medical-diagnosis/grafana helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1320,6 +1340,8 @@ spec: path: charts/all/medical-diagnosis/image-generator helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1385,6 +1407,8 @@ spec: path: charts/all/medical-diagnosis/image-server helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1450,6 +1474,8 @@ spec: path: charts/all/medical-diagnosis/xray-init helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index baad3fd0..41eb68b8 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -707,6 +707,8 @@ spec: path: common/acm helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-example.yaml" @@ -774,6 +776,8 @@ spec: path: charts/datacenter/pipelines helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-example.yaml" From e23fea077bd59d7a2291acfa512825ed2a90de01 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 17 May 2024 17:37:51 +0200 Subject: [PATCH 074/222] Use golang-external-secrets for the acm hub-ca bits We'd like to make the imperative namespace optional, so let's use the golang-external-secrets one, which is probably more correct anyways since the acm hub ca is tied to ESO anyways. --- acm/templates/policies/acm-hub-ca-policy.yaml | 2 +- golang-external-secrets/values.yaml | 2 +- tests/acm-industrial-edge-hub.expected.yaml | 2 +- tests/acm-medical-diagnosis-hub.expected.yaml | 2 +- tests/acm-normal.expected.yaml | 2 +- ...olang-external-secrets-industrial-edge-factory.expected.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/acm/templates/policies/acm-hub-ca-policy.yaml b/acm/templates/policies/acm-hub-ca-policy.yaml index 890e6bae..3d02d62f 100644 --- a/acm/templates/policies/acm-hub-ca-policy.yaml +++ b/acm/templates/policies/acm-hub-ca-policy.yaml @@ -31,7 +31,7 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}` }}' hub-openshift-service-ca.crt: '{{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}` }}' diff --git a/golang-external-secrets/values.yaml b/golang-external-secrets/values.yaml index e3d14148..8c1cab77 100644 --- a/golang-external-secrets/values.yaml +++ b/golang-external-secrets/values.yaml @@ -23,7 +23,7 @@ golangExternalSecrets: type: Secret name: hub-ca key: hub-kube-root-ca.crt - namespace: imperative + namespace: golang-external-secrets global: hubClusterDomain: hub.example.com diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 453e8a9e..620591a2 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -167,7 +167,7 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 8b50de7a..18a2f921 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -158,7 +158,7 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 66f1c590..28c5eea7 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -561,7 +561,7 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' diff --git a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml index 712ec247..f7aee2c2 100644 --- a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml @@ -12502,7 +12502,7 @@ spec: type: Secret name: hub-ca key: hub-kube-root-ca.crt - namespace: imperative + namespace: golang-external-secrets auth: kubernetes: From f6734917fc9094cb597e01521c1888bbbff4756c Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 17 May 2024 18:17:06 +0200 Subject: [PATCH 075/222] Only do the acm hub ca policy when vault is the backend The acm hub ca is needed for ESO on spokes to connect to the vault on the hub, there is no need for this when vault is not used, so let's drop it in that case --- acm/templates/policies/acm-hub-ca-policy.yaml | 7 ++++--- acm/values.yaml | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/acm/templates/policies/acm-hub-ca-policy.yaml b/acm/templates/policies/acm-hub-ca-policy.yaml index 3d02d62f..ef15b136 100644 --- a/acm/templates/policies/acm-hub-ca-policy.yaml +++ b/acm/templates/policies/acm-hub-ca-policy.yaml @@ -1,5 +1,6 @@ # This pushes out the HUB's Certificate Authorities on to the imported clusters -{{ if .Values.clusterGroup.isHubCluster }} +{{- if .Values.clusterGroup.isHubCluster }} +{{- if (eq (((.Values.global).secretStore).backend) "vault") }} --- apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -67,5 +68,5 @@ spec: operator: NotIn values: - 'true' -{{ end }} - +{{- end }} +{{- end }} diff --git a/acm/values.yaml b/acm/values.yaml index c5f222c9..6919b419 100644 --- a/acm/values.yaml +++ b/acm/values.yaml @@ -9,6 +9,8 @@ global: targetRevision: main options: applicationRetryLimit: 20 + secretStore: + backend: "vault" clusterGroup: subscriptions: From 6cd4e85d5bf7955b172b935dd05cd360fd0c4443 Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 28 May 2024 13:36:43 -0400 Subject: [PATCH 076/222] fix: when using clusterdeployments, secrets should exist in the cluster-namespace Co-authored-by: Michele Baldessari Co-authored-by: Alejandro Villegas Signed-off-by: Tomer Figenblat --- acm/templates/provision/secrets-aws.yaml | 10 ++++++++-- acm/templates/provision/secrets-azure.yaml | 10 ++++++++-- acm/templates/provision/secrets-common.yaml | 15 ++++++++++++--- tests/acm-normal.expected.yaml | 10 ++++++++++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/acm/templates/provision/secrets-aws.yaml b/acm/templates/provision/secrets-aws.yaml index a671638d..911aff4a 100644 --- a/acm/templates/provision/secrets-aws.yaml +++ b/acm/templates/provision/secrets-aws.yaml @@ -15,9 +15,9 @@ {{- $deploymentName := print .name "-" $group.name }} {{- if .platform.aws }} --- -{{- template "externalsecret.aws.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.aws.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} --- -{{- template "externalsecret.aws.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.aws.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} {{- end }}{{- /* if .platform.aws */}} {{- end }}{{- /* range .clusterDeployments */}} @@ -29,6 +29,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-creds + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: dataFrom: - extract: @@ -51,6 +54,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-infra-creds + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: openshiftPullSecret diff --git a/acm/templates/provision/secrets-azure.yaml b/acm/templates/provision/secrets-azure.yaml index 21c9d482..1ef5842c 100644 --- a/acm/templates/provision/secrets-azure.yaml +++ b/acm/templates/provision/secrets-azure.yaml @@ -16,9 +16,9 @@ {{- $deploymentName := print .name "-" $group.name }} {{- if .platform.azure }} --- -{{- template "externalsecret.azure.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.azure.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} --- -{{- template "externalsecret.azure.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.azure.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} {{- end }}{{- /* if .platform.azure */}} @@ -31,6 +31,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-creds + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: azureOsServicePrincipal @@ -57,6 +60,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-infra-creds + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: openshiftPullSecret diff --git a/acm/templates/provision/secrets-common.yaml b/acm/templates/provision/secrets-common.yaml index 474347c6..6901c79c 100644 --- a/acm/templates/provision/secrets-common.yaml +++ b/acm/templates/provision/secrets-common.yaml @@ -14,11 +14,11 @@ {{- range .clusterDeployments }} {{- $deploymentName := print .name "-" $group.name }} --- -{{- template "secret.install-config" (dict "name" $deploymentName "context" .) }} +{{- template "secret.install-config" (dict "name" $deploymentName "context" . "namespaced" true) }} --- -{{- template "externalsecret.pull-secret" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.pull-secret" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} --- -{{- template "externalsecret.ssh.private.key" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.ssh.private.key" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} {{- end }}{{- /* range .clusterDeplyments */}} {{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} @@ -28,6 +28,9 @@ apiVersion: v1 kind: Secret metadata: name: {{ .name }}-install-config + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} data: # Base64 encoding of install-config yaml install-config.yaml: {{ include "cluster.install-config" .context | b64enc }} @@ -39,6 +42,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-pull-secret + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: openshiftPullSecret @@ -65,6 +71,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-ssh-private-key + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: sshPrivateKey diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 3e6fbc74..7969434f 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -36,6 +36,7 @@ apiVersion: v1 kind: Secret metadata: name: aws-cd-one-w-pool-acm-provision-edge-install-config + namespace: aws-cd-one-w-pool-acm-provision-edge data: # Base64 encoding of install-config yaml install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLW9uZS13LXBvb2wnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCmNvbXB1dGU6Ci0gaHlwZXJ0aHJlYWRpbmc6IEVuYWJsZWQKICBhcmNoaXRlY3R1cmU6IGFtZDY0CiAgbmFtZTogJ3dvcmtlcicKICByZXBsaWNhczogMwogIHBsYXRmb3JtOgogICAgYXdzOgogICAgICB0eXBlOiBtNS54bGFyZ2UKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTEKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz @@ -46,6 +47,7 @@ apiVersion: v1 kind: Secret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy data: # Base64 encoding of install-config yaml install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLXR3by13by1wb29sJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhd3M6CiAgICByZWdpb246IGFwLXNvdXRoZWFzdC0zCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== @@ -294,6 +296,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-one-w-pool-acm-provision-edge-creds + namespace: aws-cd-one-w-pool-acm-provision-edge spec: dataFrom: - extract: @@ -315,6 +318,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-one-w-pool-acm-provision-edge-infra-creds + namespace: aws-cd-one-w-pool-acm-provision-edge spec: data: - secretKey: openshiftPullSecret @@ -372,6 +376,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy spec: dataFrom: - extract: @@ -393,6 +398,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy spec: data: - secretKey: openshiftPullSecret @@ -624,6 +630,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-one-w-pool-acm-provision-edge-pull-secret + namespace: aws-cd-one-w-pool-acm-provision-edge spec: data: - secretKey: openshiftPullSecret @@ -648,6 +655,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key + namespace: aws-cd-one-w-pool-acm-provision-edge spec: data: - secretKey: sshPrivateKey @@ -672,6 +680,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy spec: data: - secretKey: openshiftPullSecret @@ -696,6 +705,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy spec: data: - secretKey: sshPrivateKey From ff40ddc8cc1e85ba5bd6d54654c572d07ae12f1c Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 30 May 2024 10:03:47 +0200 Subject: [PATCH 077/222] Force rolebindings as early as possible This is important because in some situations (we've observed this on the clusterwide argo instance on spokes) the permissions are not there yet when argo tries to create service accounts for the imperative SAs. This means that the very first sync works up to the service account creation which then fails due to lacking RBACs. This triggers a gitops issue where selfheal never retries because the previous run failed and so the app is in a stuck loop forever Co-Authored-By: Jonny Rickard Closes: GITOPS-4677 --- clustergroup/templates/plumbing/argocd-super-role.yaml | 8 ++++++++ tests/clustergroup-industrial-edge-factory.expected.yaml | 8 ++++++++ tests/clustergroup-industrial-edge-hub.expected.yaml | 8 ++++++++ tests/clustergroup-medical-diagnosis-hub.expected.yaml | 8 ++++++++ tests/clustergroup-naked.expected.yaml | 8 ++++++++ tests/clustergroup-normal.expected.yaml | 8 ++++++++ 6 files changed, 48 insertions(+) diff --git a/clustergroup/templates/plumbing/argocd-super-role.yaml b/clustergroup/templates/plumbing/argocd-super-role.yaml index 2d5f8f76..11366a0b 100644 --- a/clustergroup/templates/plumbing/argocd-super-role.yaml +++ b/clustergroup/templates/plumbing/argocd-super-role.yaml @@ -4,6 +4,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -22,6 +26,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }}-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 356b7e7e..4e18f8cb 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -321,6 +321,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -340,6 +344,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-factory-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 3291aeb2..1af3211d 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -482,6 +482,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -501,6 +505,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-datacenter-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 6e300fc3..2d9a4d36 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -409,6 +409,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -428,6 +432,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-hub-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 6f1c6b2e..a7fee415 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -174,6 +174,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -193,6 +197,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: common-example-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 41eb68b8..7bb75394 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -371,6 +371,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -390,6 +394,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-example-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole From 113a9076b64ac070866050c31e692c2da62b3cdd Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Wed, 29 May 2024 14:06:55 -0600 Subject: [PATCH 078/222] bug: Invalid OperatorGroup generated when ommitting targetNamespaces Problem Statement: When setting a namespace like this: - openshift-distributed-tracing: operatorGroup: true targetNamespaces: [] The chart generates the following yaml: ```yaml apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: name: openshift-distributed-tracing-operator-group namespace: openshift-distributed-tracing spec: targetNamespaces: ``` Which k8s rejects the targetNamespaces key as invalid when it attempts to apply it and removes it since it doesn't have a value, which just so happens to have the desired result of not setting the targetNamespaces (or a selector) to enable it for All Namespaces. --- clustergroup/templates/_helpers.tpl | 12 +++++++++--- clustergroup/templates/core/operatorgroup.yaml | 10 +++++++--- clustergroup/templates/plumbing/applications.yaml | 2 +- tests/clustergroup-normal.expected.yaml | 2 -- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index 5001a06e..c6d14d08 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -202,13 +202,19 @@ kind: OperatorGroup metadata: name: {{ $k }}-operator-group namespace: {{ $k }} + {{- if (hasKey $v "targetNamespaces") }} + {{- if $v.targetNamespaces }} + {{- if (len $v.targetNamespaces) }} spec: targetNamespaces: - {{- if (hasKey $v "targetNamespaces") }} - {{- range $v.targetNamespaces }}{{- /* We loop through the list of tergetnamespaces */}} + {{- range $v.targetNamespaces }}{{- /* We loop through the list of tergetnamespaces */}} - {{ . }} - {{- end }}{{- /* End range targetNamespaces */}} + {{- end }}{{- /* End range targetNamespaces */}} + {{- end }}{{- /* End if (len $v.targetNamespaces) */}} + {{- end }}{{- /* End $v.targetNamespaces */}} {{- else }} +spec: + targetNamespaces: - {{ $k }} {{- end }}{{- /* End of if hasKey $v "targetNamespaces" */}} {{- end }}{{- /* End if $v.operatorGroup */}} diff --git a/clustergroup/templates/core/operatorgroup.yaml b/clustergroup/templates/core/operatorgroup.yaml index 4d8c3014..6adfef47 100644 --- a/clustergroup/templates/core/operatorgroup.yaml +++ b/clustergroup/templates/core/operatorgroup.yaml @@ -21,15 +21,19 @@ kind: OperatorGroup metadata: name: {{ $k }}-operator-group namespace: {{ $k }} + {{- if (hasKey $v "targetNamespaces") }} + {{- if $v.targetNamespaces }} spec: targetNamespaces: - {{- if (hasKey $v "targetNamespaces") }} {{- range $v.targetNamespaces }}{{- /* We loop through the list of tergetnamespaces */}} - {{ . }} {{- end }}{{- /* End range targetNamespaces */}} - {{- else }} + {{- end }}{{- /* End if $v.targetNamespaces */}} + {{- else }} +spec: + targetNamespaces: - {{ $k }} - {{- end }}{{- /* End of if operatorGroup */}} + {{- end }}{{- /* End of if (hasKey $v "targetNamespaces") */}} {{- end }}{{- /* range $k, $v := $ns */}} {{- end }}{{- /* End of if operatorGroup */}} {{- else if kindIs "string" $ns }} diff --git a/clustergroup/templates/plumbing/applications.yaml b/clustergroup/templates/plumbing/applications.yaml index 870babe3..0b9f4eda 100644 --- a/clustergroup/templates/plumbing/applications.yaml +++ b/clustergroup/templates/plumbing/applications.yaml @@ -78,7 +78,7 @@ spec: - name: global.namespace value: {{ $.Values.global.namespace }} - name: clusterGroup.name - value: {{ .Values.clusterGroup.name }} + value: {{ $.Values.clusterGroup.name }} {{- range .extraHubClusterDomainFields }} - name: {{ . }} value: {{ $.Values.global.hubClusterDomain }} diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 41eb68b8..c594b65e 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -1197,8 +1197,6 @@ kind: OperatorGroup metadata: name: exclude-targetns-operator-group namespace: exclude-targetns -spec: - targetNamespaces: --- # Source: clustergroup/templates/core/operatorgroup.yaml --- From ad87c84b9643b66e3994215dcd6cb830fcefad52 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 30 May 2024 17:26:23 +0200 Subject: [PATCH 079/222] Fix CI issue --- tests/acm-normal.expected.yaml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 8abd52ef..8e78a98f 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1219,15 +1219,17 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - - "/values-global.yaml" - - "/values-acm-provision-on-deploy.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-on-deploy.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-acm-provision-on-deploy.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-on-deploy.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern @@ -1241,10 +1243,8 @@ spec: value: apps.hub.example.com - name: global.localClusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - name: global.clusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - name: global.clusterVersion value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - name: global.localClusterName From beb71a1ba529dc6f50454ff947e2f8e547ae1cae Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 3 Jun 2024 19:09:52 +0200 Subject: [PATCH 080/222] Actually use adminServiceAccountName for the auto approve job --- .../templates/imperative/auto-approve-installplans.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/templates/imperative/auto-approve-installplans.yaml b/clustergroup/templates/imperative/auto-approve-installplans.yaml index e6ebf26c..23e6b133 100644 --- a/clustergroup/templates/imperative/auto-approve-installplans.yaml +++ b/clustergroup/templates/imperative/auto-approve-installplans.yaml @@ -16,7 +16,7 @@ spec: metadata: name: auto-approve-installplans-job spec: - serviceAccountName: {{ $.Values.clusterGroup.imperative.serviceAccountName }} + serviceAccountName: {{ $.Values.clusterGroup.imperative.adminServiceAccountName }} initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there From 39addf213792aa75d323f83c618fe49fa77c9819 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 10:39:39 +0200 Subject: [PATCH 081/222] Make sure that the if condition on chart split is not always true This should fix the fact that jobs are triggered on unrelated changes --- .github/workflows/chart-branches.yml | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml index 1a4fb455..4fb784f0 100644 --- a/.github/workflows/chart-branches.yml +++ b/.github/workflows/chart-branches.yml @@ -49,9 +49,7 @@ jobs: acm: needs: changes - if: | - ${{ needs.changes.outputs.acm == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.acm == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -63,9 +61,7 @@ jobs: golang-external-secrets: needs: changes - if: | - ${{ needs.changes.outputs.golang-external-secrets == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.golang-external-secrets == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -77,9 +73,7 @@ jobs: hashicorp-vault: needs: changes - if: | - ${{ needs.changes.outputs.hashicorp-vault == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.hashicorp-vault == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -91,9 +85,7 @@ jobs: letsencrypt: needs: changes - if: | - ${{ needs.changes.outputs.letsencrypt == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.letsencrypt == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -105,9 +97,7 @@ jobs: clustergroup: needs: changes - if: | - ${{ needs.changes.outputs.clustergroup == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.clustergroup == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write From 10b06654858958f9af5ddb7adbf7fafd65cd9b99 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 10:49:05 +0200 Subject: [PATCH 082/222] Bump super-linter from 5 to 6 --- .github/workflows/superlinter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 7430db09..ca6daab0 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -21,7 +21,7 @@ jobs: # Run Linter against code base # ################################ - name: Lint Code Base - uses: github/super-linter/slim@v5 + uses: github/super-linter/slim@v6 env: VALIDATE_ALL_CODEBASE: true DEFAULT_BRANCH: main From c85ada60e6d5be2478a5ab2941a9ceddfbe6eb3a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 10:53:41 +0200 Subject: [PATCH 083/222] Drop some validations for now --- .github/workflows/superlinter.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index ca6daab0..55acbdb0 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -29,8 +29,11 @@ jobs: # These are the validation we disable atm VALIDATE_ANSIBLE: false VALIDATE_BASH: false + VALIDATE_CHECKOV: false VALIDATE_JSCPD: false VALIDATE_KUBERNETES_KUBECONFORM: false + VALIDATE_PYTHON_PYLINT: false + VALIDATE_SHELL_SHFMT: false VALIDATE_YAML: false # VALIDATE_DOCKERFILE_HADOLINT: false # VALIDATE_MARKDOWN: false From a232db50c15ca3e3d450e8d5cdb7b4a5ed83c48a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 11:05:24 +0200 Subject: [PATCH 084/222] Add some debugging to the chart split action --- .github/workflows/chart-split.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml index 2792d6ad..ad356e61 100644 --- a/.github/workflows/chart-split.yml +++ b/.github/workflows/chart-split.yml @@ -31,8 +31,10 @@ jobs: set -e N="${{ inputs.chart_name }}" B="${N}-main-single-chart" + echo "Running subtree split for ${B}" git push origin -d "${B}" || /bin/true git subtree split -P "${N}" -b "${B}" + git remote -v git push -f -u origin "${B}" #git clone https://validatedpatterns:${GITHUB_TOKEN}@github.com/validatedpatterns/common.git -b "acm-main-single-chart" --single-branch git push --force https://validatedpatterns:"${GITHUB_TOKEN}"@github.com/${{ inputs.target_repository }}.git "${B}:main" From 821727ad13f3b779d47efd1444bb5fcda7dc4738 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 16:01:46 +0200 Subject: [PATCH 085/222] Use a specific git version when running git subtree split Otherwise we will get errors during the command as git subtree has regressed since v2.44.0 --- .github/workflows/chart-split.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml index ad356e61..39ee9c01 100644 --- a/.github/workflows/chart-split.yml +++ b/.github/workflows/chart-split.yml @@ -31,10 +31,12 @@ jobs: set -e N="${{ inputs.chart_name }}" B="${N}-main-single-chart" + GITIMG="quay.io/hybridcloudpatterns/gitsubtree-container:2.40.1" + sudo apt-get update -y && apt-get install -y podman echo "Running subtree split for ${B}" + podman pull "${GITIMG}" git push origin -d "${B}" || /bin/true - git subtree split -P "${N}" -b "${B}" - git remote -v - git push -f -u origin "${B}" + # Git subtree got broken on recent versions of git hence this container + podman run --net=host --rm -t -v .:/git "${GITIMG}" subtree split -P "${N}" -b "${B}" #git clone https://validatedpatterns:${GITHUB_TOKEN}@github.com/validatedpatterns/common.git -b "acm-main-single-chart" --single-branch git push --force https://validatedpatterns:"${GITHUB_TOKEN}"@github.com/${{ inputs.target_repository }}.git "${B}:main" From 3061644432685ff5b77276d194739e1af71c4d3b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 16:17:00 +0200 Subject: [PATCH 086/222] Release clustergroup v0.8.6 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index e2d4f98b..2ddd15ba 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.5 +version: 0.8.6 From ae14cd2bfab2a3fc7fe8cb83941b52c87c97547a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 16:22:57 +0200 Subject: [PATCH 087/222] Add a sudo to apt-get command --- .github/workflows/chart-split.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml index 39ee9c01..150e419b 100644 --- a/.github/workflows/chart-split.yml +++ b/.github/workflows/chart-split.yml @@ -32,7 +32,7 @@ jobs: N="${{ inputs.chart_name }}" B="${N}-main-single-chart" GITIMG="quay.io/hybridcloudpatterns/gitsubtree-container:2.40.1" - sudo apt-get update -y && apt-get install -y podman + sudo apt-get update -y && sudo apt-get install -y podman echo "Running subtree split for ${B}" podman pull "${GITIMG}" git push origin -d "${B}" || /bin/true From 17325d65776a7508c89f84ebbec9eebf37f04ad7 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 6 Jun 2024 08:52:27 +0200 Subject: [PATCH 088/222] Add some READMEs in the individual charts --- acm/README.md | 5 +++++ clustergroup/README.md | 5 +++++ golang-external-secrets/README.md | 4 ++++ hashicorp-vault/README.md | 4 ++++ letsencrypt/README.md | 4 ++++ 5 files changed, 22 insertions(+) create mode 100644 acm/README.md create mode 100644 clustergroup/README.md diff --git a/acm/README.md b/acm/README.md new file mode 100644 index 00000000..c8c67635 --- /dev/null +++ b/acm/README.md @@ -0,0 +1,5 @@ +# Validated Patterns ACM chart + +This chart is used to set up ACM in Validated Patterns https://validatedpatterns.io + +Please send PRs to https://github.com/validatedpatterns/common diff --git a/clustergroup/README.md b/clustergroup/README.md new file mode 100644 index 00000000..8983ddf9 --- /dev/null +++ b/clustergroup/README.md @@ -0,0 +1,5 @@ +# Validated Patterns ClusterGroup chart + +This chart is used to set up the basic building blocks in Validated Patterns https://validatedpatterns.io + +Please send PRs to https://github.com/validatedpatterns/common diff --git a/golang-external-secrets/README.md b/golang-external-secrets/README.md index e12d58f1..6d9e0f41 100644 --- a/golang-external-secrets/README.md +++ b/golang-external-secrets/README.md @@ -12,3 +12,7 @@ we just override the tag with the version + "-ubi" 4. Tweak `values.yaml` with the new image versions 5. Run `make test` 6. Commit to git + +## PRs + +Please send PRs to https://github.com/validatedpatterns/common diff --git a/hashicorp-vault/README.md b/hashicorp-vault/README.md index 26252b7e..6d5fefd6 100644 --- a/hashicorp-vault/README.md +++ b/hashicorp-vault/README.md @@ -1,5 +1,9 @@ # VP hashicorp-vault +## PRs + +Please send PRs to https://github.com/validatedpatterns/common + ## Updating the chart 1. Edit Chart.yaml with the new version diff --git a/letsencrypt/README.md b/letsencrypt/README.md index d277abaa..549e44e8 100644 --- a/letsencrypt/README.md +++ b/letsencrypt/README.md @@ -22,6 +22,10 @@ In order to enable this chart in your patterns, please add and edit the followin Once the above is enabled in a pattern, a certain amount of time (~15/20 minutes or so) is needed for all the cluster operators to settle, all the HTTPS routes will have a wildcard certificate signed by letsencrypt. By default also the API endpoint will use a certificate signed by letsencrypt. +## PRs + +Please send PRs to https://github.com/validatedpatterns/common + ## Limitations Please be aware of the following gotchas when using this chart: From 55230973793444aa5d0e43088ef9b637d17f8e33 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 6 Jun 2024 09:01:37 +0200 Subject: [PATCH 089/222] Fix super-linter issues and upgrade local super-linter target --- Makefile | 11 +++++++---- acm/README.md | 4 ++-- clustergroup/README.md | 4 ++-- golang-external-secrets/README.md | 2 +- hashicorp-vault/README.md | 2 +- letsencrypt/README.md | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 86cb5177..f9b00e57 100644 --- a/Makefile +++ b/Makefile @@ -230,17 +230,20 @@ kubeconform: ## run helm kubeconform super-linter: ## Runs super linter locally rm -rf .mypy_cache podman run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true \ + -e VALIDATE_ANSIBLE=false \ -e VALIDATE_BASH=false \ + -e VALIDATE_CHECKOV=false \ + -e VALIDATE_DOCKERFILE_HADOLINT=false \ -e VALIDATE_JSCPD=false \ -e VALIDATE_KUBERNETES_KUBECONFORM=false \ - -e VALIDATE_YAML=false \ - -e VALIDATE_ANSIBLE=false \ - -e VALIDATE_DOCKERFILE_HADOLINT=false \ + -e VALIDATE_PYTHON_PYLINT=false \ + -e VALIDATE_SHELL_SHFMT=false \ -e VALIDATE_TEKTON=false \ + -e VALIDATE_YAML=false \ $(DISABLE_LINTERS) \ -v $(PWD):/tmp/lint:rw,z \ -w /tmp/lint \ - docker.io/github/super-linter:slim-v5 + ghcr.io/super-linter/super-linter:slim-v6 .PHONY: ansible-lint ansible-lint: ## run ansible lint on ansible/ folder diff --git a/acm/README.md b/acm/README.md index c8c67635..56b39ae3 100644 --- a/acm/README.md +++ b/acm/README.md @@ -1,5 +1,5 @@ # Validated Patterns ACM chart -This chart is used to set up ACM in Validated Patterns https://validatedpatterns.io +This chart is used to set up ACM in [Validated Patterns](https://validatedpatterns.io) -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) diff --git a/clustergroup/README.md b/clustergroup/README.md index 8983ddf9..bb522d12 100644 --- a/clustergroup/README.md +++ b/clustergroup/README.md @@ -1,5 +1,5 @@ # Validated Patterns ClusterGroup chart -This chart is used to set up the basic building blocks in Validated Patterns https://validatedpatterns.io +This chart is used to set up the basic building blocks in [Validated Patterns](https://validatedpatterns.io) -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) diff --git a/golang-external-secrets/README.md b/golang-external-secrets/README.md index 6d9e0f41..4316d3a1 100644 --- a/golang-external-secrets/README.md +++ b/golang-external-secrets/README.md @@ -15,4 +15,4 @@ we just override the tag with the version + "-ubi" ## PRs -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) diff --git a/hashicorp-vault/README.md b/hashicorp-vault/README.md index 6d5fefd6..28362080 100644 --- a/hashicorp-vault/README.md +++ b/hashicorp-vault/README.md @@ -2,7 +2,7 @@ ## PRs -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) ## Updating the chart diff --git a/letsencrypt/README.md b/letsencrypt/README.md index 549e44e8..ded97205 100644 --- a/letsencrypt/README.md +++ b/letsencrypt/README.md @@ -24,7 +24,7 @@ Once the above is enabled in a pattern, a certain amount of time (~15/20 minutes ## PRs -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) ## Limitations From e3babbbaeea77385cc9f6423b4433fce15a15781 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 6 Jun 2024 10:41:00 +0200 Subject: [PATCH 090/222] Skip unreachable spokes when setting up vault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When setting up vault we loop through all the managed clusters and set up the token so ESO can fetch certain paths in vault. This happens in the unseal vault ansible job and will fail if one of the managed clusters is unreachable. This is undesirable because a cluster might have been shut down on purpose or might be temporarily not reachable and this is no reason to stop the configuration of vault. Tested as follows: 1. Deployed mcg on sno1 and sno2. All green. 2. Shut off sno2 so it is unreachable. observed unseal-cronjob fail (took a while but eventually failed with: ``` TASK [vault_utils : Fetch remote ansible to remote cluster] ******************** ok: [localhost] => (item=local-cluster) An exception occurred during task execution. To see the full traceback, use -vvv. The error was: urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.sno2.ocplab.ocp', port=6443): Max retries exceeded with url: /version (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 110] Connection timed out')) failed: [localhost] (item=sno2) => {"ansible_loop_var": "item", "changed": false, "item": {"key": "sno2", "value": {"bearerToken": "eyJhbGciOiJSUzI1... ``` 3. Imported sno3 into the hub on sno1. observed unseal-cronjob still fail: ``` TASK [vault_utils : Fetch remote ansible to remote cluster] ******************** ok: [localhost] => (item=local-cluster) An exception occurred during task execution. To see the full traceback, use -vvv. The error was: urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.sno2.ocplab.ocp', port=6443): Max retries exceeded with url: /version (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 110] Connection timed out')) failed: [localhost] (item=sno2) => {"ansible_loop_var": "item", "changed": false, "item": {"key": "sno2", "value": {"bearerToken": "ey... ok: [localhost] => (item=sno3) PLAY RECAP ********************************************************************* localhost : ok=37 changed=11 unreachable=0 failed=1 skipped=13 rescued=0 ignored=0 ``` 4. After the ignore_errors patch: ``` TASK [vault_utils : Fetch remote ansible to remote cluster] ******************** ok: [localhost] => (item=local-cluster) An exception occurred during task execution. To see the full traceback, use -vvv. The error was: urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.sno2.ocplab.ocp', port=6443): Max retries exceeded with url: /version (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 110] Connection timed out')) failed: [localhost] (item=sno2) => {"ansible_loop_var": "item", "changed": false, "item": {"key": "sno2", "value": {"bearerToken": "eyJhb.... ok: [localhost] => (item=sno3) ...ignoring # sno2 correctly gets skipped in the subsequent tasks ``` sno3 did manage to login to the vault and everything just worked Reported-by: François Charette --- ansible/roles/vault_utils/tasks/vault_spokes_init.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml index e930252a..92000b90 100644 --- a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml +++ b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml @@ -72,6 +72,11 @@ api_version: v1 validate_certs: "{{ validate_certs_api_endpoint }}" register: remote_external_secrets_sa + # We are allowed to ignore errors here because a spoke might be down or unreachable + # if a spoke is not reachable then its ['token'] field will not be set which + # will leave the ['esoToken'] field empty in the dict which will make it so that + # the spoke gets skipped + ignore_errors: true when: - clusters_info[item.key]['bearerToken'] is defined - clusters_info[item.key]['server_api'] is defined From 3ec1839635f24172ab6d1ebda88cf6983b3724a5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Jun 2024 09:28:55 +0200 Subject: [PATCH 091/222] Add no_log to spokes initialization task --- ansible/roles/vault_utils/tasks/vault_spokes_init.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml index 92000b90..060378bc 100644 --- a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml +++ b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml @@ -77,6 +77,11 @@ # will leave the ['esoToken'] field empty in the dict which will make it so that # the spoke gets skipped ignore_errors: true + # We add no_log: true here because in case of a remote failure secret bits might + # end up in the log. Unfortunately ansible is currently not easily able to control + # output in a loop (see + # https://serverfault.com/questions/1059530/how-to-not-print-items-in-an-ansible-loop-error-without-no-log) + no_log: true when: - clusters_info[item.key]['bearerToken'] is defined - clusters_info[item.key]['server_api'] is defined From 9809c86af214c3d383afc2ce2bbe03f396a688e4 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 6 Jun 2024 17:48:15 +0200 Subject: [PATCH 092/222] Drop initContainers variable and make it the default This will allow us to work with external CAs out of the box and also it will allow the framework to be able use internal gitea instances out of the box. Tested as follows: 1. Deployed stock MCG with no changes 2. Changed the MCG repo to one with this patch 3. Observed initContainers to show up on: A. namespaced argo on hub B. clusterwide argo on spoke C. namespaced argo on spoke 4. All applications still worked 5. Deployed mcg from scratch using a branch with this patch (with multisource set to false so we're sure we're testing the right common bits in the branch) --- acm/templates/policies/application-policies.yaml | 1 - acm/templates/policies/ocp-gitops-policy.yaml | 3 --- .../imperative/auto-approve-installplans.yaml | 11 ++++------- clustergroup/templates/imperative/job.yaml | 14 -------------- clustergroup/templates/imperative/unsealjob.yaml | 15 --------------- clustergroup/templates/plumbing/argocd.yaml | 7 ------- 6 files changed, 4 insertions(+), 47 deletions(-) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 2a815913..01073bd4 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -1,5 +1,4 @@ # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} {{- range .Values.clusterGroup.managedClusterGroups }} {{- $group := . }} {{- if not .hostedArgoSites }} diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index e72434ae..29204254 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -1,4 +1,3 @@ -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: @@ -54,7 +53,6 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" -{{- if $hasInitContainerCapability }} - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 @@ -215,7 +213,6 @@ spec: provider: dex tls: ca: {} -{{- end }}{{/* if hasInitContainerCapability */}} --- apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding diff --git a/clustergroup/templates/imperative/auto-approve-installplans.yaml b/clustergroup/templates/imperative/auto-approve-installplans.yaml index 23e6b133..7b935e77 100644 --- a/clustergroup/templates/imperative/auto-approve-installplans.yaml +++ b/clustergroup/templates/imperative/auto-approve-installplans.yaml @@ -20,7 +20,8 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there - {{- include "imperative.initcontainers.gitinit" . | indent 12 }} + {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} + {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} - name: auto-approve-installplans image: {{ $.Values.clusterGroup.imperative.image }} imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} @@ -39,14 +40,10 @@ spec: - "@/values/values.yaml" - common/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml volumeMounts: - {{- include "imperative.volumemounts" . | indent 16 }} + {{- include "imperative.volumemounts_ca" . | indent 16 }} containers: {{- include "imperative.containers.done" . | indent 12 }} volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} + {{- include "imperative.volumes_ca" . | indent 12 }} restartPolicy: Never {{- end }} diff --git a/clustergroup/templates/imperative/job.yaml b/clustergroup/templates/imperative/job.yaml index 0b82d47c..55400e8c 100644 --- a/clustergroup/templates/imperative/job.yaml +++ b/clustergroup/templates/imperative/job.yaml @@ -1,5 +1,3 @@ -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} - {{- if not (eq .Values.enabled "plumbing") }} {{/* Define this if needed (jobs defined */}} {{- if (and $.Values.clusterGroup.imperative (gt (len $.Values.clusterGroup.imperative.jobs) 0)) -}} @@ -24,12 +22,8 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there -{{- if $hasInitContainerCapability }} {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} -{{- else }} - {{- include "imperative.initcontainers.gitinit" . | indent 12 }} -{{- end }} {{- range $.Values.clusterGroup.imperative.jobs }} {{- if ne (.disabled | default "false" | toString | lower ) "true" }} - name: {{ .name }} @@ -60,21 +54,13 @@ spec: {{- end }} - {{ .playbook }} volumeMounts: -{{- if $hasInitContainerCapability }} {{- include "imperative.volumemounts_ca" . | indent 16 }} -{{- else }} - {{- include "imperative.volumemounts" . | indent 16 }} -{{- end }} {{- end }} {{- end }} containers: {{- include "imperative.containers.done" . | indent 12 }} volumes: -{{- if $hasInitContainerCapability }} {{- include "imperative.volumes_ca" . | indent 12 }} -{{- else }} - {{- include "imperative.volumes" . | indent 12 }} -{{- end }} restartPolicy: Never {{- end }} {{- end }} diff --git a/clustergroup/templates/imperative/unsealjob.yaml b/clustergroup/templates/imperative/unsealjob.yaml index e0ff2c78..a7553da8 100644 --- a/clustergroup/templates/imperative/unsealjob.yaml +++ b/clustergroup/templates/imperative/unsealjob.yaml @@ -1,5 +1,3 @@ -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} - {{/* If the backend is not set at all we default to "vault". See https://www.github.com/helm/helm/issues/3308 why we avoid using the default function */}} {{- if or (eq .Values.global.secretStore.backend "vault") (not (hasKey .Values.global.secretStore "backend")) }} @@ -26,13 +24,8 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there -{{- if $hasInitContainerCapability }} - {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} -{{- else }} - {{- include "imperative.initcontainers.gitinit" . | indent 12 }} -{{- end }} - name: unseal-playbook image: {{ $.Values.clusterGroup.imperative.image }} imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} @@ -55,19 +48,11 @@ spec: - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - "common/ansible/playbooks/vault/vault.yaml" volumeMounts: -{{- if $hasInitContainerCapability }} {{- include "imperative.volumemounts_ca" . | indent 16 }} -{{- else }} - {{- include "imperative.volumemounts" . | indent 16 }} -{{- end }} containers: {{- include "imperative.containers.done" . | indent 12 }} volumes: -{{- if $hasInitContainerCapability }} {{- include "imperative.volumes_ca" . | indent 12 }} -{{- else }} - {{- include "imperative.volumes" . | indent 12 }} -{{- end }} restartPolicy: Never {{- end }} {{- end }} diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml index dcce1b4b..7d42ec36 100644 --- a/clustergroup/templates/plumbing/argocd.yaml +++ b/clustergroup/templates/plumbing/argocd.yaml @@ -1,4 +1,3 @@ -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} {{- if (eq .Values.enabled "all") }} {{- $namespace := print $.Values.global.pattern "-" $.Values.clusterGroup.name }} @@ -70,7 +69,6 @@ spec: rbac: defaultPolicy: role:admin repo: -{{- if $hasInitContainerCapability }} initContainers: - command: - bash @@ -109,11 +107,6 @@ spec: {{- if len $.Values.clusterGroup.argoCD.initContainers }} {{ $.Values.clusterGroup.argoCD.initContainers | toPrettyJson }} {{- end }} -{{- else }} -{{- if len $.Values.clusterGroup.argoCD.initContainers }} - initContainers: {{ $.Values.clusterGroup.argoCD.initContainers | toPrettyJson }} -{{- end }} -{{- end }}{{/* if $hasInitContainerCapability */}} {{- if len $.Values.clusterGroup.argoCD.configManagementPlugins }} sidecarContainers: {{- range $cmp := $.Values.clusterGroup.argoCD.configManagementPlugins }} From 75f8385c1ea3c7743b52d4c13378504f8ce668a8 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Jun 2024 10:19:23 +0200 Subject: [PATCH 093/222] Update tests after dropping initContainers --- .../acm-industrial-edge-factory.expected.yaml | 155 ++++++++++++++++++ tests/acm-industrial-edge-hub.expected.yaml | 155 ++++++++++++++++++ tests/acm-medical-diagnosis-hub.expected.yaml | 155 ++++++++++++++++++ tests/acm-naked.expected.yaml | 155 ++++++++++++++++++ tests/acm-normal.expected.yaml | 155 ++++++++++++++++++ ...roup-industrial-edge-factory.expected.yaml | 71 ++++++++ ...tergroup-industrial-edge-hub.expected.yaml | 107 ++++++++++++ ...rgroup-medical-diagnosis-hub.expected.yaml | 107 ++++++++++++ tests/clustergroup-naked.expected.yaml | 71 ++++++++ tests/clustergroup-normal.expected.yaml | 107 ++++++++++++ 10 files changed, 1238 insertions(+) diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index 561fbd7b..fa867edd 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -119,3 +119,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 4199ba03..d715989d 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -327,3 +327,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index f2a8fdd6..2fd25e75 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -318,3 +318,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml index 561fbd7b..fa867edd 100644 --- a/tests/acm-naked.expected.yaml +++ b/tests/acm-naked.expected.yaml @@ -119,3 +119,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 8e78a98f..356d0658 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1330,3 +1330,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 4e18f8cb..2242f75d 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -417,6 +417,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -426,6 +445,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -477,6 +498,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -493,6 +520,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-factory + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -673,6 +709,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles sidecarContainers: - name: helm-with-kustomize command: [/var/run/argocd/argocd-cmp-server] diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 1af3211d..5e64dc60 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -578,6 +578,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -587,6 +606,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -638,6 +659,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -654,6 +681,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-datacenter + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -677,6 +713,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -686,6 +741,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -739,6 +796,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -755,6 +818,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-datacenter + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -1403,6 +1475,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles sidecarContainers: - name: helm-with-kustomize command: [/var/run/argocd/argocd-cmp-server] diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 2d9a4d36..1ea53dc6 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -505,6 +505,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -514,6 +533,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -565,6 +586,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -581,6 +608,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-hub + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -604,6 +640,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -613,6 +668,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -666,6 +723,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -682,6 +745,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-hub + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -1588,6 +1660,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles resources: limits: cpu: "1" diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index a7fee415..bd89773a 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -270,6 +270,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -279,6 +298,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -332,6 +353,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -348,6 +375,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-example + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/plumbing/argocd.yaml @@ -419,6 +455,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles resources: limits: cpu: "1" diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index bc04b88e..13daced6 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -486,6 +486,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -495,6 +514,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -546,6 +567,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -562,6 +589,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-example + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -585,6 +621,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -594,6 +649,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -647,6 +704,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -663,6 +726,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-example + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/operatorgroup.yaml @@ -1152,6 +1224,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles resources: limits: cpu: "1" From b489135f33510dc1c489e246c8c9248151a57d52 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Jun 2024 11:14:41 +0200 Subject: [PATCH 094/222] Release clustergroup v0.8.7 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 2ddd15ba..222a2482 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.6 +version: 0.8.7 From d846593fe8bd2a4be8537c93d5784afc818a27b5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Jun 2024 14:48:36 +0200 Subject: [PATCH 095/222] Upgrade ESO to v0.9.19 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.9.18.tgz | Bin 76336 -> 0 bytes .../charts/external-secrets-0.9.19.tgz | Bin 0 -> 76457 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 100 ++++++++++-------- ...-secrets-industrial-edge-hub.expected.yaml | 100 ++++++++++-------- ...ecrets-medical-diagnosis-hub.expected.yaml | 100 ++++++++++-------- ...olang-external-secrets-naked.expected.yaml | 100 ++++++++++-------- ...lang-external-secrets-normal.expected.yaml | 100 ++++++++++-------- 9 files changed, 279 insertions(+), 229 deletions(-) delete mode 100644 golang-external-secrets/charts/external-secrets-0.9.18.tgz create mode 100644 golang-external-secrets/charts/external-secrets-0.9.19.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 4aef19aa..afffe393 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.0.3 dependencies: - name: external-secrets - version: "0.9.18" + version: "0.9.19" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.9.18.tgz b/golang-external-secrets/charts/external-secrets-0.9.18.tgz deleted file mode 100644 index 7aa6d4505f93b7754cdc2f6c712ff8724153f85c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76336 zcmZsiLy#^^uwdJ^ZQQnP-?nYrwr$(Cb=$UW+jf8Rzqgr~h^dIIirm&Fv+|rGjD`aG z-vxTzJ!F?TxP}D8jtjrh*%u9!=>mDM&`IHhFHoQ_m_L~+TPzpGs;@$K8 zqWgWj@3POo1f%PJr?c2Ez|NA$CZL=Fq0jU85a|^#vUHdCGvd9u z1*erK@bTMhdOsk)NED~%)jmhic)|>Lx;O{m;QziXOv{%`HcX$7sULQGe0O`mVl-O& zA4p`nqf_o)t$^u$W#;o|jllv+Ip&&7Kb?4c5t=@%n6pNs9Z$wn{XNiR9RGY+4&I7? zKdD|)-ctuJOnc!lXduOEW-U&!5`;aleIrWO{VXv5^K&`c+Z&mn_5H9o->IlXq(Q~; zdemQ+5;}hX{O4S@R{gT8J|)7(axvC9DfGn_%{9ngg-h=TXKH=w-hZ$GPKfB2Qi@sw`pb2r!R z!j}7K>D3A|*@df;Lq#jg5w!r`!hUcgmr}T zsZ}cEQX4S|4tVVEidWy&MGDh99s(<1BXY2Bea;xm)-iEB6aevZ#vA(kn#4ORy%mzxVy7fED^tJ1SteYNDsB;b??8i{bn|> zlA2GHC=!z6^^p2&df8}kI&;L6Lp5Jsz3&D7(;pr!p^P!06v$pz08NWkcKRbad`%u? zKfF=f2V4t=WE(Z@z3zYW3jjIugtx!@dDFmh5+a_GX^G?v4O2 z=PPIAc?P@}9+nRtM}6fk?1Vq{OgYng{)8an9U!-52W5!ehP!YK>AYKa4Py(C7*_uaF5yAsFdY0`SMh!4*3BC>9 zzde)z{77V!ck~T(B#AB;^1$XfdcdR5zG*P)#Qrcc29t$j{;5V5-@88MPh8Xv_j2NAcxvC;Tyul*Y026Y z{jU0+!T$2$fII{#-v^_tfw(jgt zp(6msAm+6RNWsVk;_qA_$GfRPyxidk2zOCsmJNda_!&%z0h833aTdSgBT-gZwdNFx zgbxZGyz+Vm6(gGcupsFTLF5V{)d$`la4+tO(bb=bF)8k8PuQDee~`ME=0`tu?*ri< z8_v!%{0UU&1Il(GKfT+4ctvx2srh4NOq!WP{|2!PhT>NrHc%grGx<|TpJvzo>cDM? z&Plf102y$ro7|vi!=Cl1nIhUpIfFDo zp1H6ln=AgA#I~yHCV&LM!g8ITU3mo;xcSB%XzcX_<;9i2b$KyIluC|s16#aoWd))0 zbK8DSWeS-p>2L7%4$yvH`;#@ejR_?J=H39LMIYcpfQb;pM+V0w+Cfm$j{^hfV_?liAAI|dtT=iQ^=-J-l59FM7;)PHtz!qpLyyLv@l?TLNl_9Tep8z6{ zqC0eGffb*1FTTN?(ib<5_sR7niU{-9Ym2hzK>)n`(e-O$pBIJ=oc?We-7hv zFjVpYbEJJRc9wip?XftAa42C^^r1TF-2`oh*$4OX9TzyQoEc*(-S3UH$UJ)t?ZLgh z&1hP~lv7Cho_DI^3p_Gv0%|wH5j5%1Taqd8&9d*qakfw5UH-e8FTBqSD!`wX2YVrl zezGB$h4%$g-&&T$05}6`JJaDu5?4% zb%EAJg-CC2`f^wH6%D8(oQPj1do~9RC8pWqZ^<;XmXH3ar;RGB>DkmgzMOMv%%htzpViuaeS%^tXucqaj^C39qE#w&jwWLcy8$oQgt@&n*U%JlC-x-;Z#m#6n`)C&?pw!pt z94;hcQC&3jik&=^J7Lzmleo&ew)?MPQe9J8j~*qwpm0yHD-=O#rlvB4U~{Vud@q8p z_o1u#W?K>(cESL)?Xu_L&=F}-v5m%WJmy|;H~KqP_PPw$bKsCQ9To`?pz%LJ1PyR- zni{;@f}&*OL#K-tG4=;>PoSK5WA{m9O=WeLsF{0fqg86;uvyvLRQL+duWN*`%E7{Cv_*v34JH-t!*rD}qpZGvKbEf9~^r-j~BE!>`(f*Lrdhu9^ z5h8JfU54>(zEvmwFs)9Hm!())fkNM+M*zfrUVoI#0G7+7FC_R02BG}~7sId*N)Cp;~HH}Vcq zGfN79{A+lkid$rVQNC;SIln3Mw$6|72{7f&2DfY?@t!te>w1NU2gZN!58vbWS6c-1 zdAxpWmjm`jjB5b)s|vXlA`hSfXu@xey%PqKj~;fcoYe@6^)Ch;IkK;_K}2k|_#M4w zpcq0fE>l5Bg;V9_fW@eXSTCA{Vz#m|egIzMA{cC+rhH@B*dUp^ZQQ$&MG^R~JcZ3a zHKPQCZ@>&k_+H9AfJ45|_x2t@pC|hufDdDh`p^(^Uy0c^dD?IHD_-+^ep=7lE3^ny z_{a@uSl~YOfRW(d1k>5U{cKQp%ufn|0RXc^S_$>~UGYf>Ll+Es*|bdZS|=O*9fo@#`AU6y3%n>)dN< z$XKl4?FeI{z`J!aooxo`;fY-grp6IJxc*skyNYwUYL6AJpE-j;f^ZVo&lP)Qf+0%r zB_9Zz`$QdB;731n-~cM~0QwD7ejhD}#kk`PfcZ*ku-Bw(sVW-bUrno{=mW7PRZw^L zcWZlw$Fk|%FM|J_GHiK$Zrle9&u%sc=sp76=kn4%`Y`2lzx$HSm4D?oYmX1sHD1*% zbabBcz<;&{+h7g%CixoRq*nXXiR39MEk-XiRlU-UA*Tp8NTBXq=OPa6!I67zn%PZ- zF1iG>d>;F@!l1`nNP!X<0Gcx$lbk%)Ep}<`LLByL@D13fDAOIT>KwgkGmT>4qW+s< zXSi0l*AIOWhs{Kwy6=DuLu`P*_xUkkhd28W@VP(v!Uk;m%<#d>Lv1jWdYite?zVCp zsu94I`7e66=O&~Of>Il9ja1WV`YTw#_FW+JB^hj$A8_R!E}!4|UEk&L?=@c*Rs2GL z<=IW2fx(04$NzPPV=winFVFYwkVgXG{*Z#@Bqf9rHg-m7$re{#)v}smS5n50S=EnP zT1Jm_t0kpK#&>?CRmeC)RvMRw&ifEO+w4g8NKVDI5+G@5J7m_pbgphRXMGqRam^sA zJb51^8?MaWEp;fyHWw{3#-X=X{SOQ(*1IokEBeBWqM9h@VPo4Wa~H7>pHH<$^g-NnaGl!1N)cG0I67{C$$XUBM6we#<+6+kX4&e>ES@(LQ}Lpk>#secW=Br5 z2$KTLxJhBq5-+027?b$`2WBZ|p8DTDz+B<$C=K1F^dEK5vTDvxcorl=={w`Q99;X` z9v{ueg9{puEF-Do2us@ZY8Qkl0%I4j6NCYcNEem&d)=IYL5jCYF1a$Ulcj*G@TcIy zdK7_NZ=WcaEvgr)aFfC@N*2O>!3il*j8LF@&x9R+UA#{e=cXvGC4%X0O&`n$m)Z;v zEpia(A8i3NPkC_<1&QU}^&LyF+|nW%8LI(hvS}Q(VWC+}R|Oya)29WaGS_w)1Aa-26uvOF7M=H=pN9EBMNg(-98VBL zM>8gE@LYksPDmi&gpiqFKBS8V z6Mp1;;4=yoHu7;(0MLV5=^c1ic$|ZdJ-Q{|BOdKaXNAmeXl#NBY;s5K{E4d!7IQ`o zl5VWIhsLO-1E0x+3xRSlu}W66kU$hKj8uM&IxV!zJ7sB$}+9x_DpHm#_Q2TtaB z0t5RV>NoU&$M5AKv%I(5*J%46do57nPHiYnAhZ+KK!!v{#rj2=$>x7yz>8ZhY?@%$ z1knKC3iFP{mALpwKU8kwZc(JP%EV2}zK{pG)=< zKi?k=QrcHlpJ*#kK;5z}s?-o9rPfdD53Y~sYqGKs%_VN?KA`O#UYH17MY;QNxr-St zGE8xcdVbn0CZ5c;9KCy<^J0l6Pu~lBbs7a(4CYKA$#Tlq9(&G%4xB7iCt9X&EOAbn z5oy34yXQeTC3{&1_yg)?0sEN=KCM4G(`HWWg4EaFL}~Gx{5}l~9HUHolXkWb=F4Yk z$#vl6Oye!$z(@UQ8XS;Bf}YprRxJ`_^jdKaMymA4hlptd5=`~S0*eIlh7vO$M3nyE z_~B%HZVDPC-A6(s7I}pz$Vhw4qwHzyY}9@jEmrz`UFBn6iYZNj7V$J+;RNkF*glA4 zEnfK!RVhuL*FD*dPGT1vgDOE%NO>grA?$A(W$%IunE&k@LInu)G|0GLLL_}e2Bai@ zW*t8S6tVx`$42l6Qz}mrXgx;5ZkR|!IBDT@Gn%DSh(J30c%4N|Ya7iRcQ5=0Yo8H+ z33fOHU?&Y_yD@wxXbY83Z9DJGiAsO4k%%hgBjZ=N6S*p4!Z_-8Vhz+SJZoLfm?Orx zGsd_fPF&XH@^;VWFs{B1`n8x1o573?Xf{G=!V8^dpLW~EG7GxfMC0B+?lQvc4Bslr zrvF+Q7Cm9uQdPWnfyrRT32(szOW;=cu`JrMfEBAsKq~m#+JFAK)C3Hn`{Wz+%RA_5 zHV~1h=cjeaB`f&JT{(L#NgD6w5{3C0A_XM5~7` zK~u|&MP=m4Je0lbx&|rDelPnjTMs@1w;!-qP zFM#FYTz|+IbLWuYQ>S5~0A54jK`YZZUU>&xzFp?p6BnK#j&%FC%u;_vJ_g5fUQ%N1 zLERpq&sU9y%XSK(JD2&nr&a=p&ibZ01qh2TxL*IT@?pR!@>fZp;)rvcXFG zR|et;XQKXw={T--=I8;wCTJ+_lTiXwR5Tu<>M>_ zRahi7J^Z!T`@MV$pxm%90+-}_3J~!5yzVMLd5=GvL)85RcB9JW71TM`#ID@x>29=4B0tn|S9>v6eJ2s2=Jq@p6$vkK|(g44E*G&oU?>`QPfr z$;CkSIJ~qC4Wy=(U0DZ8^&!}FrQGE+H#h6tjXdr*9g#`^FNE^H&LMlgfS-Ll!W7l1(!g`o-W@n5$}8w3ak9*oiXHzelpy!#L0!(i-J<*Ns6d z>8q41i;{+|hSl(PqfWWGq1kd>F8%c_cX;+vH6Ep}JnG^|JG8`nc4sXN!HOn2aq0f6 zG7D=*h-|{CGFYX|31~fppHC@Jkr+p+jodqDK=xYIc)JT-p%ddDoBb=6IyhO2{V+!! znbc5A^n=C)vL4Fe+k;_o0LS-FUte9mYqRY1G(p~bH0KkK54eqN^jXtV5^y*og&c3K zL_m45z%3gCzc-0SMWe?4j|b}~jzq^}^F{ZLxWz4VT68|9Qs~-4s98ME0f6ycF!*wA z5Lt6M!gLdjmn(dhAUjrQ#N2{cf*D0@fHlwcD_?W{%Di90sAU6Z-WT%vDXbv1*dDY& zqMsa_?HgF533HAv>(}RZw4xO`fcABA+_MSje(kphZ44vA8J{Z$OJl7)3|9nWra!zOWXG+ z&`b1%RpdsAmWW-=nu~Tlj)u1+%FbGyh4vJqbNB!YuzF`}Y+*iSA9Q_JLKOa#BQX!1 zgHD7G(4E7tP=kT+#H6vyKTbrY4WefW-g~Y;&(ho41iQvSIkP|eRiSwwjj$V)WApeF zjuano)->H{E-9)yzGhV zZF*Rg7MlsTUYT!4IeV}F^vH&YW!JU*DweeKS&ww2^c7Ys^Q9yrUGcq@C^jdbv+Z$q z8jF)^gkmmNlhT#TZB8UbmpMRi8(Vr|QZ@%W@xu`9QJf8Vag`Yo&`m9~m7>0XS@GAxz(A;J(#=bvLg$EaUCgyQHvGk?|0H>py$w#o=WsIH%bRYHQJ! zHVd8D?;-6Gl=`jTNx5+|&IPsUCnL`xKOnL9X7Bh#xKn63OiEl8FOIU7b7A|OCxd4tButc9s# zmcqFdEsxhas9q~nB(-Cy27QzD27~wNGM7*si=>j-+hl?6Lh0m>{;WpQe#3hB@`oNt zpA2~NkBq#LnY{%-j@=WM@IgqEoxN;A0S-WGHHAwRv(5f=VWDAhhgsJ|zQ^QD;=0Um z+0hGKj0bjkAw|d$+pzVx$LyU*Knw13OS6S`wUNs<=6ssWx_HvWK`h6VYD-wszu_SJT?izTvi$qk~+J{%swj(0%mDR(sq7A??VJd ztd#K9DeKOubm}R`F_EgVvp=TeWxvR*O4%mNDfn)w?8eP)H!bPf8I$*k(Kz^H(WU{e zmT=)s%RW;{dcL(GZ(-w@vG_jdSGN;5Q;iGp$x$0R@&ahqEaGe8&+s^uv{FJb97bjA zorw|gx26rDII1DNqBvUDA9jn439e;iN;wW)$7**KcrLZgwl=6wR`r28^+DdigJHD! zKK!vAY6qy{4prE0t-mF4(s4bM>N0ZWd)~$q*)HUjn@z9@w_Qn6TNO=1?k+T_{((X+8PIn}~UbSgS6OJPD3g1Qwa|tPlQ!kLMAr%6*^LPlxmE z53uKc$MMscpL-U7{m%a=XxwY({qej^F1z9oh-54O(=k%y_%Shc8_hj2k;IgGq1=`-LqtO7`Rl>vuIQa+Adose=Pqeg$fP zG)uAj)m3qlH1|Efrk!sLGE(-vRwhyF0ZQL_D~||KHLB@8QvGz6q@)V70246~b9V@2U$sy5$=9U^$~_RKW%T;msS6G0rBZ=A|1t?rzsRGPK${lh(Ya_IwKU{LM zi*C8-Y^t?{8mlT|H?(d|bq~T@fxxHf@fvY{{{7^Nd*(`AFZ8o$$i(PN30FVgCBM($ z05-$6CN%YoVorQ2W!>P9(rqzSNu2YF1KO(KJds!fA`^kn6HaJ`s zd7sP}Jfp@(?;225eg%`HYOjdDJ+D2#3S-ZE z#g<*qLi&q^@n@OP`VQx%aQ%dIipwhFRixdw=`+LY0we#xEBGM%+{+zpX7$rg_I%Tm z>{$6G>Q6;>4)HCu-?AhjsvakTuCn)<<`5R6#O! zvi5PzP$2wAi{E9v{xfmNZ)FT6hn@eQ=d`LeKk!duC%MRz9n~`>rf5u`r-+X~AYwPm z^NznmQzW&Y?X=@$F|4X;9(=@iRC1?9HibPsWg|~G=IPJkL=Q}$=z?16yUXS&(D3lTF2`Y0*dDkFXZg$*GhtOgur*0#wNEAQQ6fRAA5pwyiE^^vjL@dtS`;mh0Rip!&^cpAU|$-QW?mE1AjeVga!-{y93GV@_U+} zMc9&eu&k6c}MqM^-R# zj;?xqp?>7w`GJmC10y2lvwM#20_ZAv^IaP;ShFT9J;ocXaFsr+wx!hBt-t(CWm9D# zuTS^lo+xn07YHNin%x$f*_!NCZgL(KZjFtKhy>==bcq&=**j?tj6HFi+nj~Sdar$? ze1)h#kn(G+AS9utCBl98a$wCCJ1uan!^95t2gdp88zEPBPhfeRR+(Oe9_~+^C&QB1 zB9QlM`vofmCHm(BmaLo#=pZoZDv63ty4dqw1KctF6twyme}Pjrqb)k zs&tHhg9X$KCwh7QS7Qk1V)9FB%Xm-?OSeB2akwLlUVLxDcknW(&b|}6n}H*n45
q0j)i=a#pu1jU+b_58*02a$>ktMv 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 diff --git a/golang-external-secrets/charts/external-secrets-0.9.19.tgz b/golang-external-secrets/charts/external-secrets-0.9.19.tgz new file mode 100644 index 0000000000000000000000000000000000000000..66fffaa0b08d686867fc9e4307204eaae1e22964 GIT binary patch literal 76457 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

-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 Date: Fri, 7 Jun 2024 19:49:02 +0200 Subject: [PATCH 096/222] Update helm version in CI to 3.14.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's the version gitops 1.12 is using these days: ❯ oc exec -it -n openshift-gitops openshift-gitops-repo-server-66bf746964-926qk -c argocd-repo-server -- bash -c "helm version" version.BuildInfo{Version:"v3.14.0", GitCommit:"2a2fb3b98829f1e0be6fb18af2f6599e0f4e8243", GitTreeState:"", GoVersion:"go1.21.9 (Red Hat 1.21.9-1.module+el8.10.0+21671+b35c3b78)"} --- .github/workflows/linter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 39843f26..f82194ee 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -36,7 +36,7 @@ jobs: - name: Setup helm uses: azure/setup-helm@v4 with: - version: 'v3.13.2' + version: 'v3.14.0' ################################ From 429f55cea86954bbe92c4f36094751847d8930ee Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 10:37:05 +0200 Subject: [PATCH 097/222] Drop imperative.initcontainers.gitinit Now that we switched to imperative.initcontainers.gitinit-ca, the older define is not used anywhere, so we can drop this. --- .../templates/imperative/_helpers.tpl | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index d55220e4..18735dec 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -27,48 +27,6 @@ name: ca-bundles {{- end }} -{{/* git-init InitContainer */}} -{{- define "imperative.initcontainers.gitinit" }} -- name: git-init - image: {{ $.Values.clusterGroup.imperative.image }} - imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="{{ $.Values.global.repoURL }}"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode}}` }}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.username | base64decode }}` }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.password | base64decode }}` }}')"; - URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode }}` }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; -{{- end }} - {{/* git-init-ca InitContainer */}} {{- define "imperative.initcontainers.gitinit-ca" }} - name: git-init From e967b159b31dc839d894088c1b67893c1408ed57 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 10:41:26 +0200 Subject: [PATCH 098/222] Have unseal work whenever we specifiy HEAD Otherwise if HEAD is specified we get the following: mkdir: cannot create directory '/git/home': File exists Cloning into '/git/repo'... warning: Could not find remote branch HEAD to clone. fatal: Remote branch HEAD not found in upstream origin --- clustergroup/templates/imperative/_helpers.tpl | 3 ++- tests/clustergroup-industrial-edge-factory.expected.yaml | 3 ++- tests/clustergroup-industrial-edge-hub.expected.yaml | 6 ++++-- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 6 ++++-- tests/clustergroup-naked.expected.yaml | 3 ++- tests/clustergroup-normal.expected.yaml | 6 ++++-- 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index 18735dec..c7f986e4 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -66,8 +66,9 @@ if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "{{ $.Values.global.targetRevision }}" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch {{ $.Values.global.targetRevision }}"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; {{- end }} {{/* Final done container */}} diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 2242f75d..ccd2a52c 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -473,8 +473,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 5e64dc60..2486927b 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -634,8 +634,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -769,8 +770,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 1ea53dc6..908f526f 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -561,8 +561,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -696,8 +697,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index bd89773a..4a417d5d 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -326,8 +326,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 13daced6..efb98493 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -542,8 +542,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -677,8 +678,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest From 85c3a9bec46378570b2e1df8aaa0c073151980af Mon Sep 17 00:00:00 2001 From: Trevor Royer Date: Wed, 5 Jun 2024 15:09:06 -0600 Subject: [PATCH 099/222] make resourceExclusion configurable --- clustergroup/templates/plumbing/argocd.yaml | 9 +++------ clustergroup/values.schema.json | 4 ++++ clustergroup/values.yaml | 6 ++++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml index 7d42ec36..68b692ff 100644 --- a/clustergroup/templates/plumbing/argocd.yaml +++ b/clustergroup/templates/plumbing/argocd.yaml @@ -150,12 +150,9 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun +{{- if $.Values.clusterGroup.argoCD.resourceExclusions }} + resourceExclusions: {{- $.Values.clusterGroup.argoCD.resourceExclusions | toYaml | indent 2 }} +{{- end }} {{- if .Values.global.excludeESO }} - apiGroups: - external-secrets.io diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 2955bf1a..e0331497 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -548,6 +548,10 @@ "initContainers": { "type": "array", "description": "A list of initContainers to add to the repo-server if needed" + }, + "resourceExclusions": { + "type": "string", + "description": "ResourceExclusions is used to completely ignore entire classes of resource group/kinds." } } }, diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index bb149567..94a01af9 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -28,6 +28,12 @@ clusterGroup: argoCD: initContainers: [] configManagementPlugins: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: jobs: [] From 05a876bf60fa5787cec1480394ce875dff3a5207 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 16:57:23 +0200 Subject: [PATCH 100/222] Update tests after upgrading resourceExclusions tweak --- tests/clustergroup-industrial-edge-factory.expected.yaml | 8 +++++++- tests/clustergroup-industrial-edge-hub.expected.yaml | 8 +++++++- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 8 +++++++- tests/clustergroup-naked.expected.yaml | 8 +++++++- tests/clustergroup-normal.expected.yaml | 8 +++++++- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index ccd2a52c..d651d450 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -121,6 +121,12 @@ data: --set clusterGroup.name=factory --post-renderer ./kustomize"] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -778,7 +784,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 2486927b..eec93391 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -242,6 +242,12 @@ data: --set clusterGroup.name=datacenter --post-renderer ./kustomize"] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1545,7 +1551,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 908f526f..17e26914 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -225,6 +225,12 @@ data: argoCD: configManagementPlugins: [] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1704,7 +1710,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 4a417d5d..3c8294d1 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -48,6 +48,12 @@ data: argoCD: configManagementPlugins: [] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -498,7 +504,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index efb98493..4cb54949 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -133,6 +133,12 @@ data: argoCD: configManagementPlugins: [] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1268,7 +1274,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: From e97b2e7313c4161e382ecbae8ef4bc1e093de000 Mon Sep 17 00:00:00 2001 From: Trevor Royer Date: Wed, 5 Jun 2024 14:42:50 -0600 Subject: [PATCH 101/222] Make resourcehealthchecks configurable --- clustergroup/values.schema.json | 22 ++++++++++++++++++++++ clustergroup/values.yaml | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index e0331497..b05dcb03 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -552,6 +552,13 @@ "resourceExclusions": { "type": "string", "description": "ResourceExclusions is used to completely ignore entire classes of resource group/kinds." + }, + "resourceHealthChecks": { + "type": "array", + "items": { + "$ref": "#/definitions/ArgoCDResourceHealthChecks" + }, + "description": "ResourceHealthChecks customizes resource health check behavior." } } }, @@ -585,6 +592,21 @@ "image" ] }, + "ArgoCDResourceHealthChecks": { + "type": "object", + "additionalProperties": false, + "properties": { + "check": { + "type": "string" + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + } + } + }, "IndexImages": { "type": "object", "description": "Details for overriding default catalog sources", diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index 94a01af9..cdbf823e 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -28,6 +28,26 @@ clusterGroup: argoCD: initContainers: [] configManagementPlugins: [] + resourceHealthChecks: + - kind: PersistentVolumeClaim + check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs resourceExclusions: | - apiGroups: - tekton.dev From 8d1aaab0a77c9a2c4226b46f8160409ad34fa033 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 17:23:39 +0200 Subject: [PATCH 102/222] Update tests after upgrading resourceHealthChecks change --- ...roup-industrial-edge-factory.expected.yaml | 20 +++++++++++++++++++ ...tergroup-industrial-edge-hub.expected.yaml | 20 +++++++++++++++++++ ...rgroup-medical-diagnosis-hub.expected.yaml | 20 +++++++++++++++++++ tests/clustergroup-naked.expected.yaml | 20 +++++++++++++++++++ tests/clustergroup-normal.expected.yaml | 20 +++++++++++++++++++ 5 files changed, 100 insertions(+) diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index d651d450..96cf061c 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -127,6 +127,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index eec93391..eaf5b736 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -248,6 +248,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 17e26914..e834bd9e 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -231,6 +231,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 3c8294d1..04724078 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -54,6 +54,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 4cb54949..c28834d5 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -139,6 +139,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role From 32194d1ad4c3cce0f4d7c8ce3c8877a30b83914a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 18:10:27 +0200 Subject: [PATCH 103/222] Do not quote $BRANCH variable Otherwise we might error out with: error: unknown option `branch qe_test-16831' usage: git clone [] [--] [

] --- clustergroup/templates/imperative/_helpers.tpl | 2 +- tests/clustergroup-industrial-edge-factory.expected.yaml | 2 +- tests/clustergroup-industrial-edge-hub.expected.yaml | 4 ++-- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 4 ++-- tests/clustergroup-naked.expected.yaml | 2 +- tests/clustergroup-normal.expected.yaml | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index c7f986e4..93299f91 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -68,7 +68,7 @@ if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "{{ $.Values.global.targetRevision }}" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch {{ $.Values.global.targetRevision }}"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; {{- end }} {{/* Final done container */}} diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 96cf061c..e795d287 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -501,7 +501,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index eaf5b736..8c05e007 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -662,7 +662,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -798,7 +798,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index e834bd9e..a299e7dc 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -589,7 +589,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -725,7 +725,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 04724078..ef518557 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -354,7 +354,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index c28834d5..c046404b 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -570,7 +570,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -706,7 +706,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest From 97b2afa01bffe16bf70142165b1a8e2b3ac0e1d6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 18:40:38 +0200 Subject: [PATCH 104/222] Fix initcontainer race on spokes initContainers on the clusterwide argo instances on spokes rely on a configmap called "trusted-ca-bundle" that gets created by ACM in the openshift-gitops namespace. Since we have no explicit guarantees about ordering, it might happen that the argocd object gets created by acm before the configmap. This is problematic because the init container will start but just ignore the missing configmap. Solve this by splitting the ocp-gitops-policy in two and making sure that both the openshift-gitops subscription and the trusted-ca-bundle configmap are green before applying the next dependency. --- acm/templates/policies/ocp-gitops-policy.yaml | 99 ++++++++++++++++--- .../acm-industrial-edge-factory.expected.yaml | 94 ++++++++++++++++-- tests/acm-industrial-edge-hub.expected.yaml | 94 ++++++++++++++++-- tests/acm-medical-diagnosis-hub.expected.yaml | 94 ++++++++++++++++-- tests/acm-naked.expected.yaml | 94 ++++++++++++++++-- tests/acm-normal.expected.yaml | 94 ++++++++++++++++-- 6 files changed, 511 insertions(+), 58 deletions(-) diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index 29204254..9210b47f 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -24,15 +24,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -53,6 +44,88 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 @@ -217,22 +290,22 @@ spec: apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding metadata: - name: openshift-gitops-placement-binding + name: openshift-gitops-placement-binding-argocd annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: - name: openshift-gitops-placement + name: openshift-gitops-placement-argocd kind: PlacementRule apiGroup: apps.open-cluster-management.io subjects: - - name: openshift-gitops-policy + - name: openshift-gitops-policy-argocd kind: Policy apiGroup: policy.open-cluster-management.io --- apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule metadata: - name: openshift-gitops-placement + name: openshift-gitops-placement-argocd annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index fa867edd..980d0220 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -42,6 +42,22 @@ subjects: apiGroup: policy.open-cluster-management.io --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule metadata: @@ -64,6 +80,28 @@ spec: - 'true' --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: @@ -90,15 +128,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -119,6 +148,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index d715989d..7e3bd0f3 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -70,6 +70,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -136,6 +152,28 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -298,15 +336,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -327,6 +356,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 2fd25e75..e63e0654 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -70,6 +70,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -127,6 +143,28 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -289,15 +327,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -318,6 +347,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml index fa867edd..980d0220 100644 --- a/tests/acm-naked.expected.yaml +++ b/tests/acm-naked.expected.yaml @@ -42,6 +42,22 @@ subjects: apiGroup: policy.open-cluster-management.io --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule metadata: @@ -64,6 +80,28 @@ spec: - 'true' --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: @@ -90,15 +128,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -119,6 +148,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 356d0658..f3ca998a 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -860,6 +860,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -945,6 +961,28 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -1301,15 +1339,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -1330,6 +1359,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 From ffa35ef5be91d5542e1a468b24f40de6325267b0 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 20:50:30 +0200 Subject: [PATCH 105/222] Release clustergroup v0.8.8 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 222a2482..5b774788 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.7 +version: 0.8.8 From e47dd3f883dac404f56721cd703784f0c61b4b46 Mon Sep 17 00:00:00 2001 From: Trevor Royer Date: Tue, 11 Jun 2024 09:57:54 +0200 Subject: [PATCH 106/222] configure annotation based resource tracking --- clustergroup/templates/plumbing/argocd.yaml | 1 + clustergroup/values.schema.json | 9 +++++++++ clustergroup/values.yaml | 2 ++ tests/clustergroup-industrial-edge-factory.expected.yaml | 2 ++ tests/clustergroup-industrial-edge-hub.expected.yaml | 2 ++ tests/clustergroup-medical-diagnosis-hub.expected.yaml | 2 ++ tests/clustergroup-naked.expected.yaml | 2 ++ tests/clustergroup-normal.expected.yaml | 2 ++ 8 files changed, 22 insertions(+) diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml index 68b692ff..ee1b7c2d 100644 --- a/clustergroup/templates/plumbing/argocd.yaml +++ b/clustergroup/templates/plumbing/argocd.yaml @@ -36,6 +36,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: {{ $.Values.clusterGroup.argoCD.resourceTrackingMethod}} applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index b05dcb03..a1449ff3 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -549,6 +549,15 @@ "type": "array", "description": "A list of initContainers to add to the repo-server if needed" }, + "resourceTrackingMethod": { + "type": "string", + "description": "ResourceTrackingMethod defines how Argo CD should track resources that it manages", + "enum": [ + "annotation", + "label", + "annotation+label" + ] + }, "resourceExclusions": { "type": "string", "description": "ResourceExclusions is used to completely ignore entire classes of resource group/kinds." diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index cdbf823e..f02175f9 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -28,6 +28,8 @@ clusterGroup: argoCD: initContainers: [] configManagementPlugins: [] + # resource tracking can be set to annotation, label, or annotation+label + resourceTrackingMethod: label resourceHealthChecks: - kind: PersistentVolumeClaim check: | diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index e795d287..ad6cfa3c 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -147,6 +147,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -703,6 +704,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 8c05e007..cc30a7ac 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -268,6 +268,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1470,6 +1471,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index a299e7dc..1888528f 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -251,6 +251,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1655,6 +1656,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index ef518557..56452cca 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -74,6 +74,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -449,6 +450,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index c046404b..ba0e704d 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -159,6 +159,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1219,6 +1220,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: From 5b52f0daaf9cf4a7ef392b1d32394febce6df1ea Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 15 Jun 2024 14:24:48 +0200 Subject: [PATCH 107/222] Drop imperative.volumes and imperative.volumemounts With the switch to initcontainers they are not used anywhere anymore --- clustergroup/templates/imperative/_helpers.tpl | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index 93299f91..f1d99416 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -98,22 +98,6 @@ - mountPath: /tmp/ca-bundles name: ca-bundles {{- end }} -{{- define "imperative.volumemounts" }} -- name: git - mountPath: "/git" -- name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml -{{- end }} - -{{/* volumes for all containers */}} -{{- define "imperative.volumes" }} -- name: git - emptyDir: {} -- name: values-volume - configMap: - name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} -{{- end }} {{- define "imperative.volumes_ca" }} - name: git From 28b2d3965ee10a31bc1ca03539ffd0d04f1a8cc9 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 18 Jun 2024 10:00:46 +0200 Subject: [PATCH 108/222] Properly quote vault kv command When using a password with a dollar, the oc exec commands run inside the vault are not properly escaped, casing the dollar signed to be interpreted by the shell inside the vault pod. So a password like 'Y$yxn54&qXAxpUd2*yGH' will become 'Y&qXAxpUd2*yGH' in the vault. This is because the command that is being run ends up being: oc exec -n vault vault-0 -i -- sh -c "vault kv patch -mount=secret global/mysecret dollar=Y$yxn54&qXAxpUd2*yGH" The `$yxn54` will be interpreted by the shell inside vault. Let's fix this by running a properly escaped command: oc exec -n vault vault-0 -i -- sh -c "vault kv patch -mount=secret global/mysecret dollar='"'Y$yxn54&qXAxpUd2*yGH'"'" Reported-By: Chris Butler --- ansible/plugins/modules/vault_load_parsed_secrets.py | 2 +- ansible/tests/unit/test_vault_load_parsed_secrets.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ansible/plugins/modules/vault_load_parsed_secrets.py b/ansible/plugins/modules/vault_load_parsed_secrets.py index cfcf9732..0a6aa146 100644 --- a/ansible/plugins/modules/vault_load_parsed_secrets.py +++ b/ansible/plugins/modules/vault_load_parsed_secrets.py @@ -215,7 +215,7 @@ def inject_field( for prefix in prefixes: cmd = ( f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"\"vault kv {verb} -mount={mount} {prefix}/{secret_name} {fieldname}='{fieldvalue}'\"" + f"\"vault kv {verb} -mount={mount} {prefix}/{secret_name} {fieldname}='\"'{fieldvalue}'\"'\"" ) self._run_command(cmd, attempts=3) return diff --git a/ansible/tests/unit/test_vault_load_parsed_secrets.py b/ansible/tests/unit/test_vault_load_parsed_secrets.py index ca37de94..1a449739 100644 --- a/ansible/tests/unit/test_vault_load_parsed_secrets.py +++ b/ansible/tests/unit/test_vault_load_parsed_secrets.py @@ -120,7 +120,7 @@ def test_ensure_value_injection_works(self): attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='value123'\"", + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), ] @@ -159,7 +159,7 @@ def test_ensure_b64_value_injection_works(self): attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='dmFsdWUxMjMK'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='\"'dmFsdWUxMjMK'\"'\"", # noqa: E501 attempts=3, ), ] @@ -198,11 +198,11 @@ def test_ensure_file_injection_works(self): attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='value123'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='value123'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), call( @@ -249,11 +249,11 @@ def test_ensure_file_b64_injection_works(self): attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='value123'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='value123'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), call( From 6a312d732d1cf551f552eefd5444beddac1243c3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 11 Jun 2024 15:35:49 +0200 Subject: [PATCH 109/222] Make HUB work when spokes point to in hub cluster gitea With this change we push the hub CA to the spokes in both the openshift-gitops, the namespaced argo namespace and in the imperative namespace. We do this so that the two argo instances are allowed to clone from an eventual gitea repository on the hub. Same goes for the imperative framework which might need to clone the code from the in-cluster gitea service running on the hub. --- acm/templates/policies/acm-hub-ca-policy.yaml | 158 +++++++++++++++++- acm/templates/policies/ocp-gitops-policy.yaml | 13 +- .../templates/imperative/_helpers.tpl | 10 +- clustergroup/templates/plumbing/argocd.yaml | 8 +- 4 files changed, 184 insertions(+), 5 deletions(-) diff --git a/acm/templates/policies/acm-hub-ca-policy.yaml b/acm/templates/policies/acm-hub-ca-policy.yaml index ef15b136..5759247c 100644 --- a/acm/templates/policies/acm-hub-ca-policy.yaml +++ b/acm/templates/policies/acm-hub-ca-policy.yaml @@ -36,6 +36,18 @@ spec: data: hub-kube-root-ca.crt: '{{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}` }}' hub-openshift-service-ca.crt: '{{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}` }}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}}` }} + hub-openshift-service-ca.crt: | + {{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}}` }} --- apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -68,5 +80,147 @@ spec: operator: NotIn values: - 'true' -{{- end }} -{{- end }} +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}}` }} + hub-openshift-service-ca.crt: | + {{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}}` }} +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' + +{{- end }}{{/* if (eq (((.Values.global).secretStore).backend) "vault") */}} +{{- range .Values.clusterGroup.managedClusterGroups }} +{{- $group := . }} +{{- if not .hostedArgoSites }} +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-{{ .name }}-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-{{ .name }}-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: {{ $.Values.global.pattern }}-{{ .name }} + data: + hub-kube-root-ca.crt: | + {{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}}` }} + hub-openshift-service-ca.crt: | + {{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}}` }} +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-{{ .name }}-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-{{ .name }}-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-{{ .name }}-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-{{ .name }}-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +{{- end }}{{/* if not .hostedArgoSites */}} +{{- end }}{{/* range .Values.clusterGroup.managedClusterGroups */}} +{{- end }}{{/* isHubCluster */}} diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index 9210b47f..cdc0a7e1 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -113,6 +113,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -209,7 +214,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -219,6 +224,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -239,6 +246,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index f1d99416..88538f88 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -16,13 +16,15 @@ - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles {{- end }} @@ -95,6 +97,8 @@ name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle +- mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles {{- end }} @@ -112,6 +116,10 @@ name: trusted-ca-bundle optional: true name: trusted-ca-bundle +- configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} {{- end }} diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml index ee1b7c2d..d7a8f7e3 100644 --- a/clustergroup/templates/plumbing/argocd.yaml +++ b/clustergroup/templates/plumbing/argocd.yaml @@ -74,7 +74,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: {{ $.Values.clusterGroup.imperative.image }} name: fetch-ca resources: {} @@ -83,6 +83,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -103,6 +105,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles {{- if len $.Values.clusterGroup.argoCD.initContainers }} From 591a339f7d8f8077185252d66a32194bf2e2221f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 18 Jun 2024 17:59:54 +0200 Subject: [PATCH 110/222] update tests --- .../acm-industrial-edge-factory.expected.yaml | 13 +- tests/acm-industrial-edge-hub.expected.yaml | 167 +++++++++- tests/acm-medical-diagnosis-hub.expected.yaml | 167 +++++++++- tests/acm-naked.expected.yaml | 13 +- tests/acm-normal.expected.yaml | 309 +++++++++++++++++- ...roup-industrial-edge-factory.expected.yaml | 18 +- ...tergroup-industrial-edge-hub.expected.yaml | 28 +- ...rgroup-medical-diagnosis-hub.expected.yaml | 28 +- tests/clustergroup-naked.expected.yaml | 18 +- tests/clustergroup-normal.expected.yaml | 28 +- 10 files changed, 771 insertions(+), 18 deletions(-) diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index 980d0220..39238f91 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -182,6 +182,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -278,7 +283,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -288,6 +293,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -308,6 +315,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 7e3bd0f3..83a81f06 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -38,6 +38,38 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-factory-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-factory-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-factory-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -104,6 +136,42 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-factory-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -209,6 +277,92 @@ spec: data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-factory-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-factory-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-factory + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/application-policies.yaml # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io @@ -390,6 +544,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -486,7 +645,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -496,6 +655,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -516,6 +677,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index e63e0654..edb33909 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -38,6 +38,38 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-region-one-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-region-one-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-region-one-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -104,6 +136,42 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-region-one-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -200,6 +268,92 @@ spec: data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-region-one-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-region-one-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-region-one + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/application-policies.yaml # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io @@ -381,6 +535,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -477,7 +636,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -487,6 +646,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -507,6 +668,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml index 980d0220..39238f91 100644 --- a/tests/acm-naked.expected.yaml +++ b/tests/acm-naked.expected.yaml @@ -182,6 +182,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -278,7 +283,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -288,6 +293,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -308,6 +315,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index f3ca998a..6660ae87 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -796,6 +796,70 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-acm-edge-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-acm-edge-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-acm-edge-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-acm-provision-edge-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-acm-provision-edge-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-acm-provision-edge-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-acm-provision-on-deploy-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-acm-provision-on-deploy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-acm-provision-on-deploy-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -894,6 +958,78 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-acm-edge-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-acm-provision-edge-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-acm-provision-on-deploy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -1018,6 +1154,166 @@ spec: data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-acm-edge-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-acm-edge-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-acm-edge + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-acm-provision-edge-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-acm-provision-edge-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-acm-provision-edge + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-acm-provision-on-deploy-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-acm-provision-on-deploy-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-acm-provision-on-deploy + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/application-policies.yaml # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io @@ -1393,6 +1689,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -1489,7 +1790,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -1499,6 +1800,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -1519,6 +1822,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index ad6cfa3c..49c2c1d6 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -454,13 +454,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -530,6 +532,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -555,6 +559,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -742,7 +750,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -751,6 +759,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -771,6 +781,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles sidecarContainers: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index cc30a7ac..4730754c 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -615,13 +615,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -691,6 +693,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -716,6 +720,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -751,13 +759,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -829,6 +839,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -854,6 +866,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -1509,7 +1525,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -1518,6 +1534,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -1538,6 +1556,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles sidecarContainers: diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 1888528f..76083c4e 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -542,13 +542,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -618,6 +620,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -643,6 +647,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -678,13 +686,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -756,6 +766,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -781,6 +793,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -1694,7 +1710,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -1703,6 +1719,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -1723,6 +1741,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resources: diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 56452cca..16c6d81d 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -307,13 +307,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -385,6 +387,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -410,6 +414,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -488,7 +496,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -497,6 +505,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -517,6 +527,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resources: diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index ba0e704d..0ff865e3 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -523,13 +523,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -599,6 +601,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -624,6 +628,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -659,13 +667,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -737,6 +747,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -762,6 +774,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -1258,7 +1274,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -1267,6 +1283,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -1287,6 +1305,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resources: From de5647f19c931452cda24291b344e0ae516c5ce0 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 24 Jun 2024 10:42:09 +0200 Subject: [PATCH 111/222] ACM chart version 0.0.2 --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 3bae9da5..5ab78a75 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.0.1 +version: 0.0.2 From 1fa57464d8bba92c7e7dc171634833df99f946e4 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 24 Jun 2024 10:42:36 +0200 Subject: [PATCH 112/222] golang-external-secrets chart version 0.0.4 --- golang-external-secrets/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index afffe393..2c214633 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure the golang-based external-secrets. keywords: - pattern name: golang-external-secrets -version: 0.0.3 +version: 0.0.4 dependencies: - name: external-secrets version: "0.9.19" From 89b499b3cb114c41b5d2181537430094897dcd0f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 24 Jun 2024 10:42:56 +0200 Subject: [PATCH 113/222] hashicorp-vault chart version 0.0.2 --- hashicorp-vault/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index e1577595..0fcbcb48 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure Hashicorp's vault. keywords: - pattern name: hashicorp-vault -version: 0.0.1 +version: 0.0.2 dependencies: - name: vault version: "0.28.0" From 89a4cadd511133803ebff74869bb4cbec4a98705 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 24 Jun 2024 11:00:40 +0200 Subject: [PATCH 114/222] Implement multi-source --- acm/templates/_helpers.tpl | 44 +++++++++++++ .../policies/application-policies.yaml | 64 ++++++++++++------- clustergroup/templates/_helpers.tpl | 10 ++- 3 files changed, 94 insertions(+), 24 deletions(-) diff --git a/acm/templates/_helpers.tpl b/acm/templates/_helpers.tpl index 910b3970..8302457a 100644 --- a/acm/templates/_helpers.tpl +++ b/acm/templates/_helpers.tpl @@ -11,3 +11,47 @@ Default always defined valueFiles to be included when pushing the cluster wide a # hub's cluster version, whereas we want to include the spoke cluster version - '/values-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' {{- end }} {{- /*acm.app.policies.valuefiles */}} + +{{- define "acm.app.policies.multisourcevaluefiles" -}} +- "$patternref/values-global.yaml" +- "$patternref/values-{{ .name }}.yaml" +- '$patternref/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}.yaml' +- '$patternref/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' +- '$patternref/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}-{{ .name }}.yaml' +# We cannot use $.Values.global.clusterVersion because that gets resolved to the +# hub's cluster version, whereas we want to include the spoke cluster version +- '$patternref/values-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' +{{- end }} {{- /*acm.app.policies.multisourcevaluefiles */}} + +{{- define "acm.app.policies.helmparameters" -}} +- name: global.repoURL + value: {{ $.Values.global.repoURL }} +- name: global.targetRevision + value: {{ $.Values.global.targetRevision }} +- name: global.namespace + value: $ARGOCD_APP_NAMESPACE +- name: global.pattern + value: {{ $.Values.global.pattern }} +- name: global.hubClusterDomain + value: {{ $.Values.global.hubClusterDomain }} +- name: global.localClusterDomain + value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}` }}' +- name: global.clusterDomain + value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}` }}' +- name: global.clusterVersion + value: '{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}' +- name: global.localClusterName + value: '{{ `{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}` }}' +- name: global.clusterPlatform + value: {{ $.Values.global.clusterPlatform }} +- name: global.multiSourceSupport + value: {{ $.Values.global.multiSourceSupport | quote }} +- name: global.multiSourceRepoUrl + value: {{ $.Values.global.multiSourceRepoUrl }} +- name: global.multiSourceTargetRevision + value: {{ $.Values.global.multiSourceTargetRevision }} +- name: global.privateRepo + value: {{ $.Values.global.privateRepo | quote }} +- name: global.experimentalCapabilities + value: {{ $.Values.global.experimentalCapabilities }} +{{- end }} {{- /*acm.app.policies.helmparameters */}} diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 01073bd4..5f0d132f 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -36,6 +36,46 @@ spec: - resources-finalizer.argocd.argoproj.io/foreground spec: project: default + {{- if $.Values.global.multiSourceSupport }} + sources: + - repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} + targetRevision: {{ coalesce .targetRevision $.Values.global.targetRevision }} + ref: patternref + - repoURL: {{ $.Values.global.multiSourceRepoUrl }} + targetRevision: {{ $.Values.global.multiSourceTargetRevision }} + helm: + ignoreMissingValueFiles: true + values: | + extraParametersNested: + {{- range $k, $v := $.Values.extraParametersNested }} + {{ $k }}: {{ printf "%s" $v | quote }} + {{- end }} + valueFiles: + {{- include "acm.app.policies.multisourcevaluefiles" . | nindent 26 }} + {{- range $valueFile := .extraValueFiles }} + - {{ $valueFile | quote }} + {{- end }} + parameters: + {{- include "acm.app.policies.helmparameters" $ | nindent 26 }} + - name: clusterGroup.name + value: {{ $group.name }} + {{- range $k, $v := $.Values.extraParametersNested }} + - name: {{ $k }} + value: {{ printf "%s" $v | quote }} + {{- end }} + {{- range .helmOverrides }} + - name: {{ .name }} + value: {{ .value | quote }} + {{- end }} + {{- if .fileParameters }} + fileParameters: + {{- range .fileParameters }} + - name: {{ .name }} + path: {{ .path }} + {{- end }} + {{- end }} + + {{- else }} source: repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} targetRevision: {{ coalesce .targetRevision $.Values.global.targetRevision }} @@ -53,30 +93,9 @@ spec: - {{ $valueFile | quote }} {{- end }} parameters: - - name: global.repoURL - value: {{ $.Values.global.repoURL }} - - name: global.targetRevision - value: {{ $.Values.global.targetRevision }} - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: {{ $.Values.global.pattern }} - - name: global.hubClusterDomain - value: {{ $.Values.global.hubClusterDomain }} - - name: global.localClusterDomain - value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}` }}' - - name: global.clusterDomain - value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}` }}' - - name: global.clusterVersion - value: '{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}' - - name: global.localClusterName - value: '{{ `{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}` }}' - - name: global.clusterPlatform - value: {{ $.Values.global.clusterPlatform }} + {{- include "acm.app.policies.helmparameters" $ | nindent 22 }} - name: clusterGroup.name value: {{ $group.name }} - - name: global.experimentalCapabilities - value: {{ $.Values.global.experimentalCapabilities }} {{- range $k, $v := $.Values.extraParametersNested }} - name: {{ $k }} value: {{ printf "%s" $v | quote }} @@ -92,6 +111,7 @@ spec: path: {{ .path }} {{- end }} {{- end }} + {{- end }}{{/* if $.Values.global.multiSourceSupport */}} destination: server: https://kubernetes.default.svc namespace: {{ $.Values.global.pattern }}-{{ .name }} diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index c6d14d08..0237e94a 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -3,9 +3,9 @@ Default always defined top-level variables for helm charts */}} {{- define "clustergroup.app.globalvalues.helmparameters" -}} - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: {{ $.Values.global.repoURL }} - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: {{ $.Values.global.targetRevision }} - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -18,6 +18,12 @@ Default always defined top-level variables for helm charts value: "{{ $.Values.global.clusterPlatform }}" - name: global.hubClusterDomain value: {{ $.Values.global.hubClusterDomain }} +- name: global.multiSourceSupport + value: {{ $.Values.global.multiSourceSupport | quote }} +- name: global.multiSourceRepoUrl + value: {{ $.Values.global.multiSourceRepoUrl }} +- name: global.multiSourceTargetRevision + value: {{ $.Values.global.multiSourceTargetRevision }} - name: global.localClusterDomain value: {{ coalesce $.Values.global.localClusterDomain $.Values.global.hubClusterDomain }} - name: global.privateRepo From 2e7866966f29dae91c7f3a88e92c18c32ec6d8e6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 17:36:52 +0200 Subject: [PATCH 115/222] Add tests for proper multisource support on spokes --- tests/acm-industrial-edge-hub.expected.yaml | 12 +- tests/acm-medical-diagnosis-hub.expected.yaml | 12 +- tests/acm-normal.expected.yaml | 36 ++++- ...roup-industrial-edge-factory.expected.yaml | 10 +- ...tergroup-industrial-edge-hub.expected.yaml | 70 ++++++++-- ...rgroup-medical-diagnosis-hub.expected.yaml | 130 ++++++++++++++---- tests/clustergroup-normal.expected.yaml | 20 ++- 7 files changed, 234 insertions(+), 56 deletions(-) diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 83a81f06..8b18a4da 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -438,10 +438,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: factory + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: factory - name: clusterGroup.isHubCluster value: "false" destination: diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index edb33909..dffb9eb6 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -429,10 +429,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: region-one + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: region-one - name: clusterGroup.isHubCluster value: "false" destination: diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 6660ae87..1e2b1573 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1389,10 +1389,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: acm-edge + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: acm-edge - name: clusterGroup.isHubCluster value: "false" destination: @@ -1487,10 +1495,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: acm-provision-edge + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: acm-provision-edge - name: clusterGroup.isHubCluster value: "false" destination: @@ -1585,10 +1601,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: acm-provision-on-deploy + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: acm-provision-on-deploy destination: server: https://kubernetes.default.svc namespace: mypattern-acm-provision-on-deploy diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 49c2c1d6..0d479fe4 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -650,9 +650,9 @@ spec: - "/values-4.12-factory.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -665,6 +665,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 4730754c..626b823a 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -993,9 +993,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1008,6 +1008,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1060,9 +1066,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1075,6 +1081,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1118,9 +1130,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1133,6 +1145,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1176,9 +1194,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1191,6 +1209,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1264,9 +1288,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1279,6 +1303,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1322,9 +1352,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1337,6 +1367,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1407,9 +1443,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1422,6 +1458,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 76083c4e..0b15ec3a 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -878,9 +878,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -893,6 +893,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -936,9 +942,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -951,6 +957,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -994,9 +1006,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1009,6 +1021,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1052,9 +1070,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1067,6 +1085,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1110,9 +1134,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1125,6 +1149,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1168,9 +1198,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1183,6 +1213,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1226,9 +1262,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1241,6 +1277,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1284,9 +1326,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1299,6 +1341,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1360,9 +1408,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1375,6 +1423,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1418,9 +1472,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1433,6 +1487,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1476,9 +1536,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1491,6 +1551,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1543,9 +1609,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1558,6 +1624,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1610,9 +1682,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1625,6 +1697,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 0ff865e3..9b035135 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -864,9 +864,9 @@ spec: - "/values/4.12.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -879,6 +879,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -934,9 +940,9 @@ spec: - "/values/4.12/aws.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -949,6 +955,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo From 9a3aa2b289bbb4bf6c77184254e734f58035617e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 19:13:30 +0200 Subject: [PATCH 116/222] Release clustergroup v0.8.9 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 5b774788..ab8abbf5 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.8 +version: 0.8.9 From 13f3b23d0cd7d7131b5105e472da362c1f54c282 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 20:11:21 +0200 Subject: [PATCH 117/222] Fix multisource indent error --- acm/templates/policies/application-policies.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 5f0d132f..d157e473 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -51,12 +51,12 @@ spec: {{ $k }}: {{ printf "%s" $v | quote }} {{- end }} valueFiles: - {{- include "acm.app.policies.multisourcevaluefiles" . | nindent 26 }} + {{- include "acm.app.policies.multisourcevaluefiles" . | nindent 24 }} {{- range $valueFile := .extraValueFiles }} - {{ $valueFile | quote }} {{- end }} parameters: - {{- include "acm.app.policies.helmparameters" $ | nindent 26 }} + {{- include "acm.app.policies.helmparameters" $ | nindent 24 }} - name: clusterGroup.name value: {{ $group.name }} {{- range $k, $v := $.Values.extraParametersNested }} From ac6640c6d83e931ac4b6c95d742cc92eecc3ebdb Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 20:13:02 +0200 Subject: [PATCH 118/222] Release clustergroup v0.8.10 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index ab8abbf5..b2d703a2 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.9 +version: 0.8.10 From 5f678b534a5e21c47b830194c3e4db2479e190ca Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 20:18:15 +0200 Subject: [PATCH 119/222] Release acm v0.0.3 --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 5ab78a75..b756d549 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.0.2 +version: 0.0.3 From ca9e3a2831df18ff3137fe338cd48c7f4eaf0aac Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 20:46:23 +0200 Subject: [PATCH 120/222] Fix missing chart field --- acm/templates/policies/application-policies.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index d157e473..fd7c2a3f 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -43,6 +43,7 @@ spec: ref: patternref - repoURL: {{ $.Values.global.multiSourceRepoUrl }} targetRevision: {{ $.Values.global.multiSourceTargetRevision }} + chart: clustergroup helm: ignoreMissingValueFiles: true values: | From 5bdeff5e33c49fba525e8fc21439b29bb8b26de8 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 9 Jul 2024 17:16:31 +0200 Subject: [PATCH 121/222] Release acm v0.0.4 --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index b756d549..327e0ba5 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.0.3 +version: 0.0.4 From bf0c8aac8a2d3b1e0437cd76eb57b940b49447d6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 9 Jul 2024 18:04:18 +0200 Subject: [PATCH 122/222] Update chart versions --- acm/Chart.yaml | 2 +- golang-external-secrets/Chart.yaml | 2 +- hashicorp-vault/Chart.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 327e0ba5..31fa54ea 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.0.4 +version: 0.1.0 diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 2c214633..b304d092 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure the golang-based external-secrets. keywords: - pattern name: golang-external-secrets -version: 0.0.4 +version: 0.1.0 dependencies: - name: external-secrets version: "0.9.19" diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index 0fcbcb48..ef3c22d2 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure Hashicorp's vault. keywords: - pattern name: hashicorp-vault -version: 0.0.2 +version: 0.1.0 dependencies: - name: vault version: "0.28.0" From fc675e51643b2c9ad12e86654c305ced7939f881 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 15 Jul 2024 10:17:31 -0600 Subject: [PATCH 123/222] Update vault-helm to v0.28.1 and vault to 1.17.2 --- hashicorp-vault/Chart.yaml | 2 +- hashicorp-vault/charts/vault-0.28.0.tgz | Bin 49079 -> 0 bytes hashicorp-vault/charts/vault-0.28.1.tgz | Bin 0 -> 49807 bytes hashicorp-vault/values.yaml | 2 +- ...ault-industrial-edge-factory.expected.yaml | 20 +++++++++--------- ...rp-vault-industrial-edge-hub.expected.yaml | 20 +++++++++--------- ...-vault-medical-diagnosis-hub.expected.yaml | 20 +++++++++--------- tests/hashicorp-vault-naked.expected.yaml | 20 +++++++++--------- tests/hashicorp-vault-normal.expected.yaml | 20 +++++++++--------- 9 files changed, 52 insertions(+), 52 deletions(-) delete mode 100644 hashicorp-vault/charts/vault-0.28.0.tgz create mode 100644 hashicorp-vault/charts/vault-0.28.1.tgz diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index ef3c22d2..ede5950f 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -6,5 +6,5 @@ name: hashicorp-vault version: 0.1.0 dependencies: - name: vault - version: "0.28.0" + version: "0.28.1" repository: "https://helm.releases.hashicorp.com" diff --git a/hashicorp-vault/charts/vault-0.28.0.tgz b/hashicorp-vault/charts/vault-0.28.0.tgz deleted file mode 100644 index 0e02f376d504c1c78df62986fa658fc8a73e796c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49079 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

-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

U@r}nz0LDB{;n` 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 z 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 z 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 Date: Mon, 15 Jul 2024 15:02:36 -0600 Subject: [PATCH 125/222] Release new hashicorp-vault and golang-external-secrets charts --- golang-external-secrets/Chart.yaml | 2 +- hashicorp-vault/Chart.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 802979b4..0bcc381d 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure the golang-based external-secrets. keywords: - pattern name: golang-external-secrets -version: 0.1.0 +version: 0.1.1 dependencies: - name: external-secrets version: "0.9.20" diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index ede5950f..87d3470d 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure Hashicorp's vault. keywords: - pattern name: hashicorp-vault -version: 0.1.0 +version: 0.1.1 dependencies: - name: vault version: "0.28.1" From 0983d0d872d29ddf35eeae5bc6e61d1896746a95 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Fri, 19 Jul 2024 10:54:41 -0500 Subject: [PATCH 126/222] Add Ansible playbook --- scripts/write-token-kubeconfig.yml | 90 ++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100755 scripts/write-token-kubeconfig.yml diff --git a/scripts/write-token-kubeconfig.yml b/scripts/write-token-kubeconfig.yml new file mode 100755 index 00000000..a2edd83e --- /dev/null +++ b/scripts/write-token-kubeconfig.yml @@ -0,0 +1,90 @@ +#!env ansible-playbook +--- +- name: Test k8s authentication methods + hosts: localhost + connection: local + gather_facts: false + become: false + vars: + kubeconfig_file: '~/.kube/config' + k8s_host: '{{ lookup("env", "K8S_AUTH_HOST") }}' + k8s_validate_certs: '{{ lookup("env", "K8S_AUTH_VERIFY_SSL") | default(false) | bool }}' + k8s_username: '{{ lookup("env", "K8S_AUTH_USERNAME") | default("kubeconfig") }}' + k8s_password: '{{ lookup("env", "K8S_AUTH_PASSWORD") | default(omit) }}' + k8s_api_key: '{{ lookup("env", "K8S_AUTH_TOKEN") | default(omit) }}' + k8s_ca_cert_file: '{{ lookup("env", "K8S_AUTH_SSL_CA_CERT") | default(omit) }}' + tasks: + - name: Check for pre-existing kubeconfig + ansible.builtin.stat: + path: '{{ kubeconfig_file }}' + register: kubeconfig_stat + + - name: Exit if kubeconfig found + ansible.builtin.fail: + msg: '{{ kubeconfig_file }} already exists! Exiting' + when: kubeconfig_stat.stat.exists + + - name: Get namespaces to test parameters + kubernetes.core.k8s_info: + host: '{{ k8s_host }}' + validate_certs: '{{ k8s_validate_certs }}' + username: '{{ k8s_username }}' + api_key: '{{ k8s_api_key }}' + ca_cert: '{{ k8s_ca_cert_file | default(omit) }}' + kind: namespace + when: k8s_api_key + + - name: Login explicitly + when: not k8s_api_key + block: + - name: Login explicitly to get token + kubernetes.core.k8s_auth: + host: '{{ k8s_host }}' + validate_certs: '{{ k8s_validate_certs }}' + username: '{{ k8s_username }}' + password: '{{ k8s_password }}' + ca_cert: '{{ k8s_ca_cert_file | default(omit) }}' + register: auth + + - name: Set api_key + ansible.builtin.set_fact: + k8s_api_key: '{{ auth.openshift_auth.api_key }}' + + - name: Update username if needed + ansible.builtin.set_fact: + config_k8s_username: 'kube:admin' + when: k8s_username == 'kubeadmin' + + - name: Determine clustername + ansible.builtin.set_fact: + config_k8s_clustername: "{{ k8s_host | regex_replace('https://', '') | regex_replace('\\.', '-') }}" + + - name: Write config file + ansible.builtin.copy: + content: |- + apiVersion: v1 + clusters: + - cluster: + {% if k8s_validate_certs is false %} + insecure-skip-tls-verify: true + {% endif %} + {% if k8s_ca_cert_file -%} + certificate-authority-data: {{ lookup("file", k8s_ca_cert_file) | b64encode }} + {% endif %} + server: {{ k8s_host }} + name: {{ config_k8s_clustername }} + contexts: + - context: + cluster: {{ config_k8s_clustername }} + namespace: default + user: {{ config_k8s_username | default(k8s_username) }}/{{ config_k8s_clustername }} + name: default/{{ config_k8s_clustername }}/{{ config_k8s_username | default(k8s_username) }} + current-context: default/{{ config_k8s_clustername }}/{{ config_k8s_username | default(k8s_username) }} + kind: Config + preferences: {} + users: + - name: {{ config_k8s_username | default(k8s_username) }}/{{ config_k8s_clustername }} + user: + token: {{ k8s_api_key }} + dest: '{{ kubeconfig_file }}' + mode: '0640' From 4ce4d806702d1853e1e4d117ef00fab4cd69a270 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Fri, 19 Jul 2024 11:22:08 -0500 Subject: [PATCH 127/222] Put the playbook in a more normal location for us --- Makefile | 3 +++ .../write-token-kubeconfig.yml | 1 - scripts/pattern-util.sh | 6 ++++++ scripts/write-token-kubeconfig.sh | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) rename {scripts => ansible/playbooks/write-token-kubeconfig}/write-token-kubeconfig.yml (99%) mode change 100755 => 100644 create mode 100755 scripts/write-token-kubeconfig.sh diff --git a/Makefile b/Makefile index f9b00e57..e0f0c11b 100644 --- a/Makefile +++ b/Makefile @@ -119,6 +119,9 @@ load-iib: ## CI target to install Index Image Bundles exit 1; \ fi +.PHONY: token-kubeconfig +token-kubeconfig: ## Create a local ~/.kube/config with password (not usually needed) + common/scripts/write-token-kubeconfig.sh ##@ Validation Tasks diff --git a/scripts/write-token-kubeconfig.yml b/ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml old mode 100755 new mode 100644 similarity index 99% rename from scripts/write-token-kubeconfig.yml rename to ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml index a2edd83e..e1ab10e8 --- a/scripts/write-token-kubeconfig.yml +++ b/ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml @@ -1,4 +1,3 @@ -#!env ansible-playbook --- - name: Test k8s authentication methods hosts: localhost diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index f7be58c2..8ff0c365 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -67,6 +67,12 @@ podman run -it --rm --pull=newer \ -e EXTRA_HELM_OPTS \ -e EXTRA_PLAYBOOK_OPTS \ -e KUBECONFIG \ + -e K8S_AUTH_HOST \ + -e K8S_AUTH_VERIFY_SSL \ + -e K8S_AUTH_SSL_CA_CERT \ + -e K8S_AUTH_USERNAME \ + -e K8S_AUTH_PASSWORD \ + -e K8S_AUTH_TOKEN \ -v "${PKI_HOST_MOUNT}":/etc/pki:ro \ -v "${HOME}":"${HOME}" \ -v "${HOME}":/pattern-home \ diff --git a/scripts/write-token-kubeconfig.sh b/scripts/write-token-kubeconfig.sh new file mode 100755 index 00000000..f9b0c8a0 --- /dev/null +++ b/scripts/write-token-kubeconfig.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -eu + +get_abs_filename() { + # $1 : relative filename + echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" +} + +SCRIPT=$(get_abs_filename "$0") +SCRIPTPATH=$(dirname "${SCRIPT}") +COMMONPATH=$(dirname "${SCRIPTPATH}") +PATTERNPATH=$(dirname "${COMMONPATH}") +ANSIBLEPATH="$(dirname ${SCRIPTPATH})/ansible" +PLAYBOOKPATH="${ANSIBLEPATH}/playbooks" +export ANSIBLE_CONFIG="${ANSIBLEPATH}/ansible.cfg" + +PATTERN_NAME=${1:-$(basename "`pwd`")} + +ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "${PLAYBOOKPATH}/write-token-kubeconfig/write-token-kubeconfig.yml" From 41bc42df584b2ff0c6c3f6f1b6f6599e06e8c23a Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Fri, 19 Jul 2024 12:58:43 -0500 Subject: [PATCH 128/222] Exclude new playbook --- .ansible-lint | 1 + 1 file changed, 1 insertion(+) diff --git a/.ansible-lint b/.ansible-lint index aaffc6b5..0522976e 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -16,5 +16,6 @@ exclude_paths: - ./ansible/playbooks/iib-ci/iib-ci.yaml - ./ansible/playbooks/k8s_secrets/k8s_secrets.yml - ./ansible/playbooks/process_secrets/process_secrets.yml + - ./ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml - ./ansible/playbooks/process_secrets/display_secrets_info.yml - ./ansible/roles/vault_utils/tests/test.yml From 7bcfbd33e6617ca545baf89fd63ab256dac1bdd1 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Fri, 26 Jul 2024 12:40:02 -0500 Subject: [PATCH 129/222] Allow for choice in where file is written --- .../write-token-kubeconfig/write-token-kubeconfig.yml | 4 ++++ scripts/write-token-kubeconfig.sh | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml b/ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml index e1ab10e8..dcb23111 100644 --- a/ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml +++ b/ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml @@ -87,3 +87,7 @@ token: {{ k8s_api_key }} dest: '{{ kubeconfig_file }}' mode: '0640' + + - name: Notify user + ansible.builtin.debug: + msg: "Wrote {{ kubeconfig_file }}" diff --git a/scripts/write-token-kubeconfig.sh b/scripts/write-token-kubeconfig.sh index f9b0c8a0..12a2bb80 100755 --- a/scripts/write-token-kubeconfig.sh +++ b/scripts/write-token-kubeconfig.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash set -eu +OUTPUTFILE=${1:-"~/.kube/config"} + get_abs_filename() { # $1 : relative filename echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" @@ -14,6 +16,4 @@ ANSIBLEPATH="$(dirname ${SCRIPTPATH})/ansible" PLAYBOOKPATH="${ANSIBLEPATH}/playbooks" export ANSIBLE_CONFIG="${ANSIBLEPATH}/ansible.cfg" -PATTERN_NAME=${1:-$(basename "`pwd`")} - -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "${PLAYBOOKPATH}/write-token-kubeconfig/write-token-kubeconfig.yml" +ansible-playbook -e pattern_dir="${PATTERNPATH}" -e kubeconfig_file="${OUTPUTFILE}" "${PLAYBOOKPATH}/write-token-kubeconfig/write-token-kubeconfig.yml" From 98d43123834d24fafb670e4127244cddc07763d5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 6 Aug 2024 10:03:38 +0200 Subject: [PATCH 130/222] Fix pki bind mount when using podman machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we test for the existance of local TLS folder and bind mount them in containers. This does not work correctly when using podman machine, because a the test is running on the host and so we might bind mount the wrong folder. For example: On Mac OSX /etc/pki does not exist on the folder and so we bind mount /etc/ssl even though /etc/pki does exist in the podman machine VM Co-Authored-By: Ákos Erős --- scripts/pattern-util.sh | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 8ff0c365..508e1531 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -49,13 +49,20 @@ if [ -n "$KUBECONFIG" ]; then fi fi -# Use /etc/pki by default and try a couple of fallbacks if it does not exist -if [ -d /etc/pki ]; then - PKI_HOST_MOUNT="/etc/pki" -elif [ -d /etc/ssl ]; then - PKI_HOST_MOUNT="/etc/ssl" +# Detect if we use podman machine. If we do not then we bind mount local host ssl folders +# if we are using podman machine then we do not bind mount anything (for now!) +REMOTE_PODMAN=$(podman system connection list -q | wc -l) +if [ $REMOTE_PODMAN -eq 0 ]; then # If we are not using podman machine we check the hosts folders + # Use /etc/pki by default and try a couple of fallbacks if it does not exist + if [ -d /etc/pki ]; then + PKI_HOST_MOUNT_ARGS="-v /etc/pki:/etc/pki:ro" + elif [ -d /etc/ssl ]; then + PKI_HOST_MOUNT_ARGS="-v /etc/ssl:/etc/ssl:ro" + else + PKI_HOST_MOUNT_ARGS="-v /usr/share/ca-certificates:/usr/share/ca-certificates:ro" + fi else - PKI_HOST_MOUNT="/usr/share/ca-certificates" + PKI_HOST_MOUNT_ARGS="" fi # Copy Kubeconfig from current environment. The utilities will pick up ~/.kube/config if set so it's not mandatory @@ -67,13 +74,7 @@ podman run -it --rm --pull=newer \ -e EXTRA_HELM_OPTS \ -e EXTRA_PLAYBOOK_OPTS \ -e KUBECONFIG \ - -e K8S_AUTH_HOST \ - -e K8S_AUTH_VERIFY_SSL \ - -e K8S_AUTH_SSL_CA_CERT \ - -e K8S_AUTH_USERNAME \ - -e K8S_AUTH_PASSWORD \ - -e K8S_AUTH_TOKEN \ - -v "${PKI_HOST_MOUNT}":/etc/pki:ro \ + ${PKI_HOST_MOUNT_ARGS} \ -v "${HOME}":"${HOME}" \ -v "${HOME}":/pattern-home \ ${PODMAN_ARGS} \ From ec340b1ae64004c9f92c14bb9c30bdc408628ca1 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 8 Aug 2024 11:55:06 +0200 Subject: [PATCH 131/222] Allow originRepo to be set via make install and main.git parameters We introduce the `main.git.repoUpstreamURL` parameter. This can be used to set `originRepo`. When `originRepo` is set, an in-cluster gitea will automatically be spawned. In this case `originRepo` will point to the upstream repository and `targetRepo` will point to the internal in-cluster gitea mirror. --- clustergroup/values.schema.json | 4 ++++ operator-install/templates/pattern.yaml | 3 +++ operator-install/values.yaml | 5 +++++ tests/operator-install-industrial-edge-factory.expected.yaml | 2 +- tests/operator-install-industrial-edge-hub.expected.yaml | 2 +- tests/operator-install-medical-diagnosis-hub.expected.yaml | 2 +- tests/operator-install-naked.expected.yaml | 2 +- tests/operator-install-normal.expected.yaml | 2 +- 8 files changed, 17 insertions(+), 5 deletions(-) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 384f79ef..2f43a6ff 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -81,6 +81,10 @@ "revision" ], "properties": { + "repoUpstreamURL": { + "type": "string", + "description": "Upstream URL of the pattern's git repository. When set an in-cluster gitea instance gets spawned and repoURL is ignored" + }, "repoURL": { "type": "string", "description": "URL of the pattern's git repository" diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index 728726f0..c33d7e8a 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -6,6 +6,9 @@ metadata: spec: clusterGroupName: {{ .Values.main.clusterGroupName }} gitSpec: +{{- if .Values.main.git.repoUpstreamURL }} + originRepo: {{ .Values.main.git.repoUpstreamURL }} +{{- end }} {{/* if .Values.main.git.repoUpstreamURL */}} targetRepo: {{ .Values.main.git.repoURL }} targetRevision: {{ .Values.main.git.revision }} {{- if and .Values.main.tokenSecret .Values.main.tokenSecretNamespace }} diff --git a/operator-install/values.yaml b/operator-install/values.yaml index a46cca2e..6c1b124c 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -3,6 +3,11 @@ global: main: git: + # Uncommenting this will set the `originRepo` with the below value + # when `originRepo` is set, an in-cluster gitea will automatically be spawned. + # In this case `originRepo` will point to the upstream repository and `targetRepo` + # will point to the internal in-cluster gitea mirror + # repoUpstreamURL: https://github.com/validatedpatterns/multicloud-gitops repoURL: https://github.com/pattern-clone/mypattern revision: main diff --git a/tests/operator-install-industrial-edge-factory.expected.yaml b/tests/operator-install-industrial-edge-factory.expected.yaml index 5e4aa02e..6400a5a9 100644 --- a/tests/operator-install-industrial-edge-factory.expected.yaml +++ b/tests/operator-install-industrial-edge-factory.expected.yaml @@ -22,7 +22,7 @@ metadata: namespace: openshift-operators spec: clusterGroupName: example - gitSpec: + gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main multiSourceConfig: diff --git a/tests/operator-install-industrial-edge-hub.expected.yaml b/tests/operator-install-industrial-edge-hub.expected.yaml index 5e4aa02e..6400a5a9 100644 --- a/tests/operator-install-industrial-edge-hub.expected.yaml +++ b/tests/operator-install-industrial-edge-hub.expected.yaml @@ -22,7 +22,7 @@ metadata: namespace: openshift-operators spec: clusterGroupName: example - gitSpec: + gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main multiSourceConfig: diff --git a/tests/operator-install-medical-diagnosis-hub.expected.yaml b/tests/operator-install-medical-diagnosis-hub.expected.yaml index 5e4aa02e..6400a5a9 100644 --- a/tests/operator-install-medical-diagnosis-hub.expected.yaml +++ b/tests/operator-install-medical-diagnosis-hub.expected.yaml @@ -22,7 +22,7 @@ metadata: namespace: openshift-operators spec: clusterGroupName: example - gitSpec: + gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main multiSourceConfig: diff --git a/tests/operator-install-naked.expected.yaml b/tests/operator-install-naked.expected.yaml index 3d58b474..b6647318 100644 --- a/tests/operator-install-naked.expected.yaml +++ b/tests/operator-install-naked.expected.yaml @@ -22,7 +22,7 @@ metadata: namespace: openshift-operators spec: clusterGroupName: default - gitSpec: + gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main multiSourceConfig: diff --git a/tests/operator-install-normal.expected.yaml b/tests/operator-install-normal.expected.yaml index 5e4aa02e..6400a5a9 100644 --- a/tests/operator-install-normal.expected.yaml +++ b/tests/operator-install-normal.expected.yaml @@ -22,7 +22,7 @@ metadata: namespace: openshift-operators spec: clusterGroupName: example - gitSpec: + gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main multiSourceConfig: From 73313cbeb8613f792ddc41387f99791851fb5990 Mon Sep 17 00:00:00 2001 From: day0hero Date: Thu, 8 Aug 2024 12:19:56 -0500 Subject: [PATCH 132/222] resolves #21 rag-llm-gitops --- scripts/pattern-util.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 508e1531..70357f67 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -38,7 +38,8 @@ else MYNAME=$(id -n -u) MYUID=$(id -u) MYGID=$(id -g) - PODMAN_ARGS="--passwd-entry ${MYNAME}:x:${MYUID}:${MYGID}:/pattern-home:/bin/bash --user ${MYUID}:${MYGID} --userns keep-id:uid=${MYUID},gid=${MYGID}" + PODMAN_ARGS="--passwd-entry ${MYNAME}:x:${MYUID}:${MYGID}::/pattern-home:/bin/bash --user ${MYUID}:${MYGID} --userns keep-id:uid=${MYUID},gid=${MYGID}" + fi if [ -n "$KUBECONFIG" ]; then From 99bc297ef7ea2c2fa5e4a16901265ab5899b0447 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 12 Aug 2024 08:55:13 +0200 Subject: [PATCH 133/222] Fix vars that were erroneously dropped In 98d43123834d24fafb670e4127244cddc07763d5 (Fix pki bind mount when using podman machine) we erroneously dropped some K8S_* variables. Reported-by: Andrew Beekhof --- scripts/pattern-util.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 70357f67..c434ca83 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -75,6 +75,12 @@ podman run -it --rm --pull=newer \ -e EXTRA_HELM_OPTS \ -e EXTRA_PLAYBOOK_OPTS \ -e KUBECONFIG \ + -e K8S_AUTH_HOST \ + -e K8S_AUTH_VERIFY_SSL \ + -e K8S_AUTH_SSL_CA_CERT \ + -e K8S_AUTH_USERNAME \ + -e K8S_AUTH_PASSWORD \ + -e K8S_AUTH_TOKEN \ ${PKI_HOST_MOUNT_ARGS} \ -v "${HOME}":"${HOME}" \ -v "${HOME}":/pattern-home \ From 58b6958471e8e56356732f1db2de0a8e2290c670 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 13 Aug 2024 16:34:11 +0200 Subject: [PATCH 134/222] Allow more flexibility with multiSourceConfig schema We specifically also add helmRepoUrl as it make it more discoverable, but we stay flexible in what we accept so that things can be extended without having to be in lockstep with the operator. --- clustergroup/values.schema.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 2f43a6ff..38eaeb57 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -107,11 +107,15 @@ }, "multiSourceConfig": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "enabled": { "type": "boolean", - "description": "Enable the experimental support for multi source" + "description": "Enable the experimental support for multi source for the clustergroup chart" + }, + "helmRepoUrl": { + "type": "string", + "description": "The helm repo URL for the clustergroup chart" } } }, From 3c28c4bfce3f02bd19782911e23f26dc352535b5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 20 Aug 2024 09:23:18 +0200 Subject: [PATCH 135/222] Inject VALUES_SECRET env var Since it can be used to point to an alternative file, let's inject it into the container --- scripts/pattern-util.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index c434ca83..8fa4a26f 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -74,6 +74,7 @@ podman run -it --rm --pull=newer \ --security-opt label=disable \ -e EXTRA_HELM_OPTS \ -e EXTRA_PLAYBOOK_OPTS \ + -e VALUES_SECRET \ -e KUBECONFIG \ -e K8S_AUTH_HOST \ -e K8S_AUTH_VERIFY_SSL \ From 7ed4d1e0f0adaaf82c0ed14aa80da091b245119e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 21 Aug 2024 14:36:34 +0200 Subject: [PATCH 136/222] Add helmRepoUrl variable --- operator-install/templates/pattern.yaml | 3 +++ operator-install/values.yaml | 1 + 2 files changed, 4 insertions(+) diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index c33d7e8a..3eda9482 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -17,6 +17,9 @@ spec: {{- end }} {{/* if and .Values.main.tokenSecret .Values.main.tokenSecretNamespace */}} multiSourceConfig: enabled: {{ .Values.main.multiSourceConfig.enabled }} +{{- if .Values.main.multiSourceConfig.helmRepoUrl }} + helmRepoUrl: {{ .Values.main.multiSourceConfig.helmRepoUrl }} +{{- end }} {{/* if .Values.main.multiSourceConfig.helmRepoUrl */}} {{- if .Values.main.analyticsUUID }} analyticsUUID: {{ .Values.main.analyticsUUID }} {{- end }} {{/* if .Values.main.analyticsUUID */}} diff --git a/operator-install/values.yaml b/operator-install/values.yaml index 6c1b124c..6a77c086 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -17,6 +17,7 @@ main: multiSourceConfig: enabled: false + # helmRepoUrl: registry.internal.network/helm # String to enable certain experimental capabilities in the operator and the # framework. Not needed unless you know exactly what you're doing. From 9ec9af0aefcf77e923caf5ca3a5eb70558a01403 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 22 Aug 2024 16:10:46 +0200 Subject: [PATCH 137/222] Update letsencrypt to v0.1.1 --- letsencrypt/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/letsencrypt/Chart.yaml b/letsencrypt/Chart.yaml index 899c790e..d8a9810f 100644 --- a/letsencrypt/Chart.yaml +++ b/letsencrypt/Chart.yaml @@ -7,7 +7,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.0 +version: 0.1.1 # 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 From 5ec42ac2cdf9226019053178429ae13de3e57b15 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 23 Aug 2024 06:39:27 +0200 Subject: [PATCH 138/222] Allow overriding gitops source on spokes This is needed on spokes when installing in a disconnected environment --- acm/templates/policies/ocp-gitops-policy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index cdc0a7e1..1d54b78d 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -38,7 +38,7 @@ spec: channel: {{ default "gitops-1.12" .Values.main.gitops.channel }} installPlanApproval: Automatic name: openshift-gitops-operator - source: redhat-operators + source: {{ default "redhat-operators" .Values.main.gitops.operatorSource }} sourceNamespace: openshift-marketplace config: env: From e6511e726e12a920e5fa9792cc1fdaa280379142 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 23 Aug 2024 06:40:44 +0200 Subject: [PATCH 139/222] Update acm chart to v0.1.1 --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 31fa54ea..3a7663b4 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.1.0 +version: 0.1.1 From 1a5cce870e9a95a0e17f8831637666266da7596a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 23 Aug 2024 06:41:02 +0200 Subject: [PATCH 140/222] Update clustergroup chart to 0.8.11 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index b2d703a2..18fa4dfb 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.10 +version: 0.8.11 From 9ccd486a29de051228ab0c9fd0bde8e465503a20 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 23 Aug 2024 08:14:20 +0200 Subject: [PATCH 141/222] Extend the schema for disconnected --- clustergroup/values.schema.json | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 38eaeb57..2fbe3421 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -97,11 +97,29 @@ }, "gitops": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "channel": { "type": "string", "description": "The channel from which to install the gitops operator" + }, + "operatorSource": { + "type": "string", + "description": "The catalog source from which to install the gitops operator" + } + } + }, + "patternsOperator": { + "type": "object", + "additionalProperties": true, + "properties": { + "channel": { + "type": "string", + "description": "The channel from which to install the patterns operator" + }, + "source": { + "type": "string", + "description": "The catalog source from which to install the patterns operator" } } }, From b3cef81938b59b35e7a319fd76ab1b42eb39e5b8 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 23 Aug 2024 08:18:56 +0200 Subject: [PATCH 142/222] Update clustergroup chart to 0.8.12 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 18fa4dfb..2bacbfc5 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.11 +version: 0.8.12 From a8d7f944e30b76ba42592732051c6ea7ed08d27e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 26 Aug 2024 09:15:25 +0200 Subject: [PATCH 143/222] Update super-linter to v7 --- .github/workflows/superlinter.yml | 5 ++++- Changes.md | 2 +- Makefile | 5 ++++- ansible/roles/iib_ci/README.md | 2 +- ansible/roles/vault_utils/README.md | 2 +- golang-external-secrets/README.md | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 55acbdb0..8c1e8035 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -21,7 +21,7 @@ jobs: # Run Linter against code base # ################################ - name: Lint Code Base - uses: github/super-linter/slim@v6 + uses: github/super-linter/slim@v7 env: VALIDATE_ALL_CODEBASE: true DEFAULT_BRANCH: main @@ -31,10 +31,13 @@ jobs: VALIDATE_BASH: false VALIDATE_CHECKOV: false VALIDATE_JSCPD: false + VALIDATE_JSON_PRETTIER: false + VALIDATE_MARKDOWN_PRETTIER: false VALIDATE_KUBERNETES_KUBECONFORM: false VALIDATE_PYTHON_PYLINT: false VALIDATE_SHELL_SHFMT: false VALIDATE_YAML: false + VALIDATE_YAML_PRETTIER: false # VALIDATE_DOCKERFILE_HADOLINT: false # VALIDATE_MARKDOWN: false # VALIDATE_NATURAL_LANGUAGE: false diff --git a/Changes.md b/Changes.md index ed7d4bf6..8ade8ad6 100644 --- a/Changes.md +++ b/Changes.md @@ -124,7 +124,7 @@ ## October 3, 2022 * Restore the ability to install a non-default site: `make TARGET_SITE=mysite install` -* Revised tests (new output and filenames, requires adding new result files to git) +* Revised tests (new output and filenames, requires adding new result files to Git) * ACM 2.6 required for ACM-based managed sites * Introduced global.clusterDomain template variable (without the `apps.` prefix) * Removed the ability to send specific charts to another cluster, use hosted argo sites instead diff --git a/Makefile b/Makefile index e0f0c11b..785e5307 100644 --- a/Makefile +++ b/Makefile @@ -238,15 +238,18 @@ super-linter: ## Runs super linter locally -e VALIDATE_CHECKOV=false \ -e VALIDATE_DOCKERFILE_HADOLINT=false \ -e VALIDATE_JSCPD=false \ + -e VALIDATE_JSON_PRETTIER=false \ + -e VALIDATE_MARKDOWN_PRETTIER=false \ -e VALIDATE_KUBERNETES_KUBECONFORM=false \ -e VALIDATE_PYTHON_PYLINT=false \ -e VALIDATE_SHELL_SHFMT=false \ -e VALIDATE_TEKTON=false \ -e VALIDATE_YAML=false \ + -e VALIDATE_YAML_PRETTIER=false \ $(DISABLE_LINTERS) \ -v $(PWD):/tmp/lint:rw,z \ -w /tmp/lint \ - ghcr.io/super-linter/super-linter:slim-v6 + ghcr.io/super-linter/super-linter:slim-v7 .PHONY: ansible-lint ansible-lint: ## run ansible lint on ansible/ folder diff --git a/ansible/roles/iib_ci/README.md b/ansible/roles/iib_ci/README.md index 8c654dbb..de4b4107 100644 --- a/ansible/roles/iib_ci/README.md +++ b/ansible/roles/iib_ci/README.md @@ -1,6 +1,6 @@ # IIB Utilities -A set of ansible plays to fetch an IIB (Image Index Bundle, aka a container created by the operator sdk +A set of ansible plays to fetch an IIB (Image Index Bundle, aka a container created by the operator SDK that contains a bunch of references to operators that can be installed in an OpenShift cluster) Run `ansible-playbook common/ansible/playbooks/iib-ci/lookup.yml` to see which IIBs are available (defaults to diff --git a/ansible/roles/vault_utils/README.md b/ansible/roles/vault_utils/README.md index 7198752c..6b851f2a 100644 --- a/ansible/roles/vault_utils/README.md +++ b/ansible/roles/vault_utils/README.md @@ -55,7 +55,7 @@ By default, the first file that will looked up is The paths can be overridden by setting the environment variable `VALUES_SECRET` to the path of the secret file. -The values secret yaml files can be encrypted with `ansible-vault`. If the role detects they are encrypted, the password to +The values secret YAML files can be encrypted with `ansible-vault`. If the role detects they are encrypted, the password to decrypt them will be prompted when needed. ### Version 1.0 diff --git a/golang-external-secrets/README.md b/golang-external-secrets/README.md index 4316d3a1..b6feb981 100644 --- a/golang-external-secrets/README.md +++ b/golang-external-secrets/README.md @@ -11,7 +11,7 @@ we just override the tag with the version + "-ubi" 3. Run `./update-helm-dependency.sh` 4. Tweak `values.yaml` with the new image versions 5. Run `make test` -6. Commit to git +6. Commit to Git ## PRs From 3fbf2e838a468ed0fca3258098b47fdc9fe3d4e0 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 26 Aug 2024 09:23:34 +0200 Subject: [PATCH 144/222] Fix action path --- .github/workflows/superlinter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 8c1e8035..3ab8cf27 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -21,7 +21,7 @@ jobs: # Run Linter against code base # ################################ - name: Lint Code Base - uses: github/super-linter/slim@v7 + uses: github/super-linter/super-linter/slim@v7 env: VALIDATE_ALL_CODEBASE: true DEFAULT_BRANCH: main From 97b958939d113a05b156199d651589e0a37b7c70 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 26 Aug 2024 09:25:44 +0200 Subject: [PATCH 145/222] Fix action path v2 --- .github/workflows/superlinter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 3ab8cf27..03b6fff9 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -21,7 +21,7 @@ jobs: # Run Linter against code base # ################################ - name: Lint Code Base - uses: github/super-linter/super-linter/slim@v7 + uses: super-linter/super-linter/slim@v7 env: VALIDATE_ALL_CODEBASE: true DEFAULT_BRANCH: main From 55beff384848b550aa2e8c1aad2ef9187a253e6b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 26 Aug 2024 08:22:37 +0200 Subject: [PATCH 146/222] Upgrade ESO to v0.10.0 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.10.0.tgz | Bin 0 -> 82278 bytes .../charts/external-secrets-0.9.20.tgz | Bin 81759 -> 0 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 237 ++++++++++++++---- ...-secrets-industrial-edge-hub.expected.yaml | 237 ++++++++++++++---- ...ecrets-medical-diagnosis-hub.expected.yaml | 237 ++++++++++++++---- ...olang-external-secrets-naked.expected.yaml | 237 ++++++++++++++---- ...lang-external-secrets-normal.expected.yaml | 237 ++++++++++++++---- 9 files changed, 964 insertions(+), 229 deletions(-) create mode 100644 golang-external-secrets/charts/external-secrets-0.10.0.tgz delete mode 100644 golang-external-secrets/charts/external-secrets-0.9.20.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 0bcc381d..22a56453 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.1.1 dependencies: - name: external-secrets - version: "0.9.20" + version: "0.10.0" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.10.0.tgz b/golang-external-secrets/charts/external-secrets-0.10.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..28d7b4a50628a89cf964745ac0dc68cc2f1fdb53 GIT binary patch literal 82278 zcmV(?K-a$?iwFP!000001MEF(bK^FW^I5+Fr(`R3)}$p_wkN9d-a4MSi7S(d%bsNG z>gs9(k&uL#A{jp9(MfJNc) zi`|z2l=IV5{QvO$bddeOE-!}Tv$GR;d~$aFVlW&J&xS9^=@Z~mDsdRmfRGnUZY`L@ zYTIq9|C1J0G}ByJO}O%PG6A0&M;^w z|IhhPef~2GLhiW}vKsZM@25Wp=5SyRdN%W!Yctp4ES&TVVtKC3Bhh5aqX!y5oe|pi zAVR^41txRp)M0jy5SK1lbt9+@nD2!=@`Ck*cov@=AI}$7U~=!cB$F1(WC(p$S=`Jq zpcYyI_a!o~RW~BLktKEMoGqCfk(n2e@8c;{vxtSgg@<@8qR0<%SRO6nscCu3^2o&p zJ#OJpx@$lmOxZn#c|lbKqqT!{yrkScreP>5L(g!$IsAtPb7uPPym!ym4_;skir*)w z8zqDcqW{8H3G=@C+XWe#!*9%iG5D&7V@2>U)FM0vznuxWXO6?&rA1fX`tNgmhNvfe zlNI+p`KvT=wD#dK2#mumiX7-A+);w_xn+A_HkTUx?|9bz&c@iF{|6_hXJ!3A*z5o2 zC`IM|^eUUrSr|=7xS*rcv&rmiV4t$Fbw=&+$!KPsvza{|*wj8bIX@rM8Ko~@vcYI- zzZ|jYH}>ghG(I^Wy&S!qox_hQ>&+QxH5xH{Li(e@XlxA5jM3oza4;DRC#NHG{LRbp z@UMf>WH9LOHBzaR7#Fdn?*Kh_xD)8^|DO#{&-ecSbCd@Dzx(n1>pL_05N$igCjEal zEb9OBv*F2J|3615@}DedNT!Ur1T2H&t(i^2*s@p{&SJ+|6YdHV5&G0($(~1K?ZxDQI}ULfAONkwOD3^T zD3ML>zy`4%IQ3T!@Q($Vr(mQ)FAe~^1N8dY2MP$XBQjkRXakNaj7P~=D;hh|S6Og} zX0P`H0^lxmTnd+#z(3J~5u49uEWn)vdc7g>X4#%0p{`99-UDI^n}8Xg#{dU9E_)Vr zVXCkJiJ=Kh7*Hc`#ExNtG3-uSoh;mqFG#~_)XJ{h19X0U~d9w3lG+Ru0Spd! z!XN^9h3#evW8*xP`79x-u1pB4n$*^}A-oeNaK03im|V2yY>Hz-4hh7(m9&z5HJ-VL z9g*_`?nX1x|4V56CF~bq$wAx8S@oY%`d&%iq}C5siQw@OG8JenqD)Jm4>!_A(u!gb zDr~usl*z2%b5dK!=-LKZg5@YAk=!tIweB(kjoLzO>`<76P^%RpTRC*foHl|jny0fZ zax*Jv@^2O40#3qi)Isd~f9;e0Kl|O)iMLz=Ac1Nd=E#N;S1<)jGhE1RuCV0XwVc>) zn4&3>XlNJ$V=Qne-l~Dj%sNuDzf9t@SO@yfOk;z%4^MX6sc(_#@;m5CFDml83`Isx zZDYEYfV9Niv0%khd3gXoCXqc$P*b9=W*T|_MVC%GjY|2dC%EyzrVG!ze{#Yn1ML}5 zNf%?uU^!X&74Ue1R!mpIpOC)l*ngJkSuBVQG*E%(I4pR2IV%phm$ydxbeFqU1a6YQ z0)QRLAsC!Hg-v^tQ^en>L|?{i8%0$5jy2N<_bj5W#qzw*dT5y$ZPeCJfU}1EWVmmV zn_bMIFvfOsNxib-rY%%UmRgn9C@`0fPn0Izmy3b-$khDdI{1Y53%e57;}1}uO=GTchZ%%LkU4%%$c1hhPv z#UoR}&_+4kxlQ!uO}0yuhU7p!is&3%lO&oT{HN4wIV_G)qGo=uZARKa*jvnv1{kdY zv+p|$g*#wCRkmU-Sqc6D&1sazIduHA4Q&GfUJ{oOMP7_BUx%b0f=}YkVRB*^BAUoX zk?-iIrZ{u*AtDMwLZocl1J(F<<*6K&x|JwkWJnOjfs0#fCa?nm`_X6a-Ga{|!b2Gz z2f|nwF2k8)@Vxg^2-KfQiK#UOJWL>=jl?lq$YZusRw}QkPp91B5r;K(d2_9J9Gc%z zq$acCfJbZ7gWe(b7T)tPg&}5W6lhRI4_9O`gkF;{uM{z-6yqQ&W#9+iirbhz$+yys zuBD0;io1NTJ~^uRdVEbp&FHIo%a$2QqB2{vkQQK-bQo(m3)E zXxkN`#ymVsrizn2{+isfrMJqiL$!a?5p2O~-M-AY3*s$#RC?T>g>M2c_WPtC#O`JI zQ;51r{;evE99$r}>qR9YfZuPq8-MswoXZO{ow}iu2U8qeugdc8y7h~HSC6DlEcO!( zS?c?_(=<<38uEX|-FO0|N8^*z;XeQO97U~T)N?idsPdNNNp z5wPhGLiZ%ceh+1gAw5+L``i!=ZSS7D_Jq7jgs8V<5iG=rPLdO+ja%u=#<6NUP14NF zq}#y+=qdv;lhmBFjxae%Wa)R}ay&^Fk#Xu)`#UAVi)~!0&lY%YQY(?90SfE*zw2CX385sb-ZHYB^xpwcpd*(K+ zj>1kp0h6D~2DTNw$doe~)qRj^--CHX4({1H6y$RlY;uQ(Sz6`5wG_zCo09zYqa7Pd z4;Ee+y<^dX7u+|IInyldtM=pKg$F%FeY&}9I@&Iy;&!LBm^$;Lktff`m*J>9mmDu@ zABvT{!E~z_lESJGgy~o0t@^4*lU_MgS^f%iP_f*2VB6MBaw8)|e$qA%hz9d8%Lzk> zO{LTr#4xPDHUjor%wlG6pm4CF&P9{q6iu&H%lyy?Pw5VElH{U`U!+qd_27i-bJ5jB z%0t6eyTdJkwmoVpm1j`f4lXA33`kOo;JGjt6m1Zdfh`zyqQyrEtcjV_22~S=H-R^0 zCbotj0Ip&DLZ9mK9dGWi6>AbCXkv;s<=!8uZ$x~_4CY!MMu0bf!M3ke(@M>j-2s5S zhiYq3aR#@93oZ}AxC_ls&Cas2@M`<2CgRNPhK{ugER!b?`8LP7x_uRvF_sG4@IfdqPY64d??`BDa7FtO1gJp9 zR<%+XW4PLF3M0o--luuWkx;>K#Q1CR3MR zSb6;LwaquIU|{7;ns+%H)~WzPqs4?AW83w|Tpf2giqI?O&^0U)&$VG!HX7vG_$=VU z*ORrU9effYKCj(X9wp|k%6>$JU)|d9H=&@9+!rJ`dAwUp>N9UuUyj;v&oX!#I$u2lj%`*f?l-6kaI zY=-M=U5{YWBHhoaCr^r4>R{E6N?Du0${Uq)`L5f|gUyk3f%p_{pUO1ar?iqgVkk zhvajoBmOitqJ#bqrqp`W#ZVjc|H;Ylq@e##24`n`{r?(q^)>Hb%J&gVF@7MBNNM2i&*rfFl)g?;@uMplv^52*2yU$GC=W64inS61R`FL{WF z25ipJm(Osg4(AnhxGi3_S5lx~il@(sc^!73mwgX+Bvp9i#?B)3@Tj3ytY#d!WVV}# z63S;Hr{#Hp&D}Qq7cVYs#H&DpYFrG%*g{i$3lBgF{}c)X(7k0dgsExYFk5I}YN79Vqn{>>o@2A$>3Cp~lyvu}0_B~Z%4S^Oly~oXZ0`RjU224Z}sMLlGdI{-|QyBw1-}%=Q)8kWKfM6Os{L*c!=f zXEqsGOi$(m5W9;ujJJ$7bl3mtExrzBV3YnI4U78!bhzLDKTp|K|5v|U`S?gcQT=N_ zubUO<;+6ifg1#D5^C`p}%|+@rf4aBXFjVN|4#VxxEbX25&t97Je_-$C64>tdzn%|= zqy7D_&rvq zalrN%UwHOhApL~o0;19-%PWh}RClv`LG@`}y(^u|VCRO`%2SiL;l-YFFW~7BIioOo zCS-Vdb$cl)-X|3p6aT)V@+~}*SD`z8+Pg0m~NggP~^u3l~J9D71vQGF4JC2k}6D#Q+CXw=Zy14?J2Q=7)Zd zceyH@1rKaudk?O>=9Oi>Z$RXkdU;=piGpg1_IYsEE&vM^D7*|qUaer)%t(@4PRQ)_ za-i-Q161%1vWm~r2(F+hKAt+>RDL-I8y{a@zA}EijH89Qv@_uR0PqPSUOai5QRlhm z&B7uCCb>^T%~4+bp=1_sxe)RvZ~Os5040HWzyo!SHY#J{iPVBw0)8jHFA?IpiXEFs zEgb<2%bUCWV*)+Yd=mZ%$c?K$_#=+KAECZ4!Cule0K#!e>}DX!yIab*BsYNP7@^G_ zUj7#2(a~d}{rEISb#-i`upEbcZqUG5aJ&pfFwEzMn2alo0`TaIBv)1#SO(_gl`pv} zp}{&b3l$qmBUJ$9WK*8tBP8SP>$~^qb?Jg{l0|9L3JPg%A!UJ3;w}{Ei3UwT)#+7v z8?3|8PKWVy$s-ht-+<~7GO`T#O4xm&PDCouE;oS%cLi$Exk7{a+`JQ4zZ=Mq*4!(; zg`DpoiJhy;zFpgv-Fanx2N04qs_vxM-$)TGk@~Yjp<`j@+|<1=?}*cvmuQ1XJuJWn zCP8WvQ16%75VGozYqip1UwA7FH?W5S*gBPl1raSjZSI3b-I{W(Y(;gW0{wr;_dyDT z%4(`AlGGJxC~TN$TP9jNjIn6bc3sj7wMbvjUI?q0lD(3c!_GLC45BDme#FkV~yvD~v-O;J0A4NTPqXNvFSsp$d! zf%xJI{*X*a%=K3x`2{V@FY?Z(%(67e9e&(EUnUwRKACKYW_!w7p`-kBW*>JYu0s7y{*Y-nRnkyHM#E(A%6RNaLGO=BC3Qt6fYa_PF-FBRZ~ zI5NQZ3k>)RELX~x!pK!$=Uo*^D3Jef9TYJ-W&u7xd3 zRqM&MHc?##_K#+owlzyFDZ1H+V3FCQ?abANCXLn1UGczk@ovla*sh|#BJ70R#8Zb` zSB@7~MU>iz#q0cN1r?@42LL~dR}!ZVRUi|!O(l5Cb6uFExH;doD^QV-7hR7Cbwd0&DkI=2H$`3No`Kg7!WxM( z(bwb=6^$~~3C+3p#oOWOs1msh%Z|uTcW*FeE4ryiR}1b^_4gYVEU8<^UgpNjYEd>e z2nMz&4PDbN#iyo0Gm?!uIwl5;>`1=AQAE#x2E8t z_#S)LNyvQkBWIvKj3}(TNQ7!fA)9G9k_cm7_!yJKx>D?%Gl|#g)u1jPOYYP!=2ub6 zie#}EOS)A>DC___JI!oy(uevgiiw|4G7|4TQsoKRas2!CLEJ& zs&O6CQ6|f^k@pMMK*kueoHy4$z`qlC^V?!Y)X;bD(fg_R>}n+?gGUsVQ4_T-sTzt zX2s*0rCVb(D;}et3?q`vjdK{67k6!DpT*OPTedLZALFYN*34(D%e+~xiM!@=nMy!igdczm*d|L<8!?$YA& zA<)D0Y5B&_*Ged4;Irc5|NVi{{ejWO1EZDNrPX24N1YHYj3b`sUZc-Tw5U%{idMEM z9T=^ilC-B4=SKBWu=KEKC4gRXW>jI(D<2pI$r3AwI_UC1n=8ByGH;204L$cpSU7p8 zk>w_HC(b#h_xRqjnOO)VNWO{Mk^@t4p30*sFa15Q0I83A>MOCkK^G1WE>}r{@W21# z;O{2(ySV7z;+3rZ!~apODn^F-=Hc{N+$rd$ZI9wsijn@3n(UkGpsIxlPh)0X*!^+O zr0kD-?vH!^UpnqtsVs6wJmvQnL$T{c1t%g%mEDRIY|1(1?ZOW=^D3c>QANjd`SIo+e3? zY*Ivbt@pG#5TWe0w3-4gx5T#QG1y)#>lR1}lUKMnvddQ|7(9G0C3;{?p1=7%`8c>f zS|UCpgPRnrzLCMuKnz?n?uJxl4y`;rwnCB|2zL(=Gyffa|Lw3E>-wBnyL@=SmR`g* zoE7MrTD;Xj3ke)Kn38xgA4Q%G@Z_m^)$KsJQ2)!`zc06KWDDcy{GF#jF}2H1l}Or& zlbPc>bM~i5PDW!pR*ACxP3_thHAzT91OnUuC|SwQWBp#>_hhHn>I)hmfL=|45wX!_4c?DOqixk{fplTbE*N8@`)6yS!C0LlY1~L_H`Zu&aD57#YFeFBP(uWd4Ao#5|86#d0c(`+`0CCm7%W7co*# z6VWDVS@g?E8V)+*g8Dodg{>WLl6tx_goY{4gqa>taYdRe3fb)`C?okDTYhr@ddYmX zge+8@Avex@x@}esY`i6f?i+Wst8LKSVc<^ir`*|x=;tY3!fP8+abr0qYS0SD1;~fv z9l<|H7ECHoMU0M(^FWmiKz}3xpQFmS$i0=}Jp|xb&qJsddgjL_YS4gzJ4}w|dVT}J z^CROoOgJ83C(B5P(@JoPr-pt6U@Ql#G4IgLgDu!6LxKyQcXp;TY&!LU6?V|vJ-L52 z#y8knR!$s;uH|pA4QhrmB4WK4o-}%O3cZ#Gr%sGCgHw1x zvpUjo>8PEoxoApfpi`FTcWE|1sOO{L zsJT!=u$Aylu_JzHwQyb2)}*PQz|m$wNhKjSXl^W;1l8Qo!G;%~7*-QhUWK_&t)72s z{*~Xb^&*?!5T`O3@(bhpi#>W_zpRB(Rl)Jt@2cPDLh49a;IPzyb@tLst3~BZ@CR=X zQh;ap6F4bQbf6s%b7jK^dr>38=VCM`0grX1)D!C9K+!00sAyx+k9hkv< zLgSi&RU^A9^#ElA5hq_^v)i~;`%1$|nB8+`iD7j^LP~~{LznR2yB!Ozc*&wnLKu=h zU|j82FlF#pNb1O6WPp-3x=C{01zeWU|B=L&`~;(Vp2YJc&0lz)ssxxO_)9N}7}w+m>BAsPA?lJr*jx(Ug_&^k zL=+7`6kd3Ckh|nU;E3M7PB(|TjTX{yoXup3y8XU1LvSbWvZ$~;oXx1O99sD+y+-}V zWx=_ZtFTb6#Ea7XSN2mpj%Aj&O4D#ArztOyO3SQbe8FbPWe$vYUoPWFWh9K*eV8f5 zOYrnE%5n?_jagoFt3*k8J6wXW=qtv+$62(uYKu$_=|Jn=!3#H|-S`raFAorbb8UVi`d_8{$-snr~GK ztgoGj(E#~^u|w=)(=*v%J1+WhR58=_^h3EfGP)+wH{Lm8NzTQ15;L{Uiv)ahuYxV~ ztTOZ^G0#d_-U|t zdrtFeD(Vn>V$JiK*Mlk>A~H;anhx-k*lg!e`{zfsiHnqN0`G#<(7X$hcR}(lNVdM- z1xYvWg7io(NIf_O$&3#wsYAPOkR)Z#+l-aeJAPK3P?@jU0u!FX`9=#!5qgPFT6uvB z>n*T=0lR`!d|JO{UWKJi$@PK7(Ok>`q32@ML6Q#+g25^u1W)-Z8vMWiPd@mD|6zfD z#{ai~|93rT9rvwBf1Zb^>H0m)Qo|{VzhYT+IpP~kW;M(6^VXt(HG0wMWz?Hrp@ zaHtJ)y5P&5W64c$BMHse@L*rqkFXd@=JO8xX2nC@nm2`9S|`Wn!@(e(O@eoKNyj6f zhjD23K7#~`ZTYXMSFQR2&V}yJ3P1$o&H0stM&NSg-+8n4m&Qk6Y;WK8>DR}F6}DXBCx8g z4A?pBd0F8GG=YSzSFae%K2m;;BXdnPcBmg3Ow;1m^6*OCy8<2yrkq)Z+DAp1qD`k>|{F&^0mQe5t{F^ zK`PO>+tY?=qtVEZ)5hB~g_*4*^N_+iD(RTUK02`&BHdhLAc=W2YU;D}8X?zMrTd0% zNzO_xC&PGmZnAw}KV7F~U=G`&i8XxOG`1pL{aZ%#7Id}3lUKcA_f1wL8nHm3*_^#= z^oR144;|NNVA>CM`{a6~dg)f%aI?waLvX!2Oy(PXzaezpJQB*K+9C>?7DvQg)sO5Y zvdTuc1C--CK+F|ZL-8ERy-E6hXpZ2F`7*M0O?=bXWT@n%a;u_w?B}sx$A=#Kt$*aP z-+FTdr;Cqn8FST@Prz(0uVhFc7DInZL4^Fx8|3@@NA%9jyZz!8EmZ*&aiT%P7+6y$*o{(N>rE$ZMvHdh+6^#qZZl&;?$LztmTsW7+PI zHM;)UDB^+@v+Gx7C<4huT>nUsgN zSh?^w$_h$-`Vwo%mqic6**wVwwBb%(M@#8r z92TWVt4*;a+&|O=;&z@SkPe`L|9SN(f?5c0gvV)^^S|O>dV!Q!V4rZ3elc*h6M?`1 z5N3r5{vc&hXAM){`y>G`2(e`wLO0!SV1mUe$AS<^nhZIkTiiF!AmPaW!vy2TlgWwD zoFje_1x-MGIuGV6+%Qwc@S>Sz9#s88*p4loH%UGr(`725{WQGMo&-ZcxF}s_ofn0qOEa}q9bY#md*Su@vMjc-3&f%CbqN%kM ziSP@AVynq4iXjY16&4kQng4Pf&TdTLf$NqKbecBZv9osEIBX~iSnJeYh7$_|*T*Cj z;>7PNzQyS@hk~hn*5WLy8aEwQ#|yLE+8^Ig~Yn7j? zKf?^0prfugwn3H6S8JarNuk|4Jl77`G7(HK^))XUf5`J+==kv`{J?zTOvYCle?mkk zhAz{&aN=fND^)qsxOcq^SmP=St76J!ZQ*>tWt`q4u?6H66)459ye+ei{gLUhi9)_! zuzC984<-cfAmK-m-6M%{fu?Aruszr|an)zo8J2u^ecu$uP(OI1HY{##m+!xOk}Y02 zh6Ib6=nk*twCSs+7juWvd#%qpxMn)T^B2#5 z_~9?lU;Oa>ci(;g*S~(p|NiZFfBpWuzXZ>mX4$Z!PQDciprb6$xK9FVQhYIgqf7i zAmMWYJ%3^RET4h;PYD7W zl2O0Qr#hPP2lf_Y1v63~HlLp)zoGnhxV~)YIb6uD99$809nRPg(owYGfIt5nZ;EAV zfGCB!;Z>N7K+vA9qIfP=qY!Iw`)u_5`_Z$ns(~d1gQR+c zZ~l8ESjn}iCUv>2fiIaGE^G$hAO@)AHp@AVUKqh=9EQo^>B)!hCbb`$1&31 zi#Cy>JwcpJn+Y(G5uv8CLf$FRRv>(Yh$+oms zMTMe293L$pG0*)N(NQ#Afg)}^4{yVGoJUtfmd&m?*E}ouX^%O$hq#$UWI12Vzt)^; zBUjwOPB*2Zu^rZHnVFGQEJEd($Ryms*{jL95x5TLCXUFsyX~h1kmZ01Gx4QPc*N-e zWrsr3iFS0|sD)19)i5?88|orTY+Y=c zD0UOx$NX?eUfPGUbGgM_z&2OuyYl;FrVAphfSoBn`T&6wwtQ(64-2*CpFbWhqxWZT z$j&HwDL;P%>KDAv;(GmWwRVy61GAA4YJiihi)>X~i`Q#ONLgJo|H_0n=Cd))^Dr!6 zv>E!d;1f~%?8TKuTh?GDeLFoE8LT??0cz|eM;?mEO@wCUa5jSke%46}Ox}ujRF|p) zeBqRz1e#Nl0L&YEa!d*RsXz@@r#D`M&yW+J>vS#$A4ZgS}AlpZPi8kwVv;c92tESmXMMNmAb}g@mQ@90@D0w1*3~l}cVV^Qs2_ z{CJL;Qb;phR$n)aU47o*s>38?b0c{Q^n$G7!a0sK*9AV33uRr9VQx4BkSvuGyjl+z zewp%p0ofzXQnM1P6j1EX0ACz`DC?0&Ta7+!mJjsI#U>v1%CrJ$M zJ(#5UI)K*!6~7X>L`T6Uke4LS4i1SgB;_lCfUZJu8_F=Uvyvw+QKoBN1zl;lrXf55 zl$|qVwRXA%i*>GJ9}d^2)Y#QhkvD8MIJrs$3AVK;%L64cP z+u_RPiFtPfd8feLynaKv)dUK@`Y&DNS7e~&Xu<2tzloQnw zuwC#4T<{mmqJ>UhRfj8{C3&Kj!{LAg1=3v@$HSW>y-N&h3eJqx4^GY|hv4b^^U-PW zG0kq`l+A+^u$4rO!gF&g&=CRMdlh)~fwJW?Oy)vZM%ABEo!gsZ{*DcjKDcI8=#ko0 zI7LtOz8I?KTJwpR2g8Aw(pNClf-Rw|Ax&C(lh;ZX?_BTZnKH?Uh!mAiyApIHBqRQB zLIMpK#n5Qb6*JHtMA2}rS?ohO1iUMxwsrbXNC)brGwN2nbk@TbJe}He=}e%db3zIq zXq%kSVQEH}QH07a^aSDz5#wTY;Mz^4$s#9EIM00c2f+m&_Cgq8)iV`1!0WC&cJ$cM zW5-Rf<0;G7&WaOz6e*iWk!{VRNY{OM6j_e**a_ZA-Dd2^RWf%daAP^)(^qfD;9K;= z3yu(GDQGf}4udJqq3dAWLXHX${7a`3Vem$eZot7%L|ixpS@rU=zRqFI@g;!&i9-%LO+l5n_3-Sy=! z(`>d0e8lH~qjmrrlL?7)6703_eg2z8&>w z_3i+Kazh6qE+3B$HBSS9Z3pdPtz{#>Y6>anBmvSj6+NfH7rI#AP;XgV$Vk6&#VXV? z3{ETHj@r|#Zm>p5#@qEkd{_quXbCoPr}Gt50?qZ&AAnV7aHQ%{4EidgL#U!AI_jzW z0T(qTid9|S5$kO(sFTW2s#(_k7Q4EdzJe|NtgGS(ZOW#tWp}D>hN7>VXQ%w;C{9=N zUK~3u9)?XTR{oJfL(dHRF(7;XZ?s&p=A;rXi-VSBxmy*ZL(>F+RfO|G!%aZ(>}+z_ zr#&Ez<}-z(4l`@fF=$R~9E^Vs=IEcIIK+6LzGukNINZg`bCDc}>fGoswu}9&c0R-} zDi9}pBVkDBX+Y(1jdaF?)~GMIPNAw-u0%zt%n-?9G|r+ua%k>`wb$YO$uY@oyKz%M zpbyJ|yoJpxNUCe~3KFj%sdabKA#=1ML&EyOQS#DxJmv9JWvw1hc|29?z9ZMND#zvW zSq%|Bpo%#QulSYfcEW0ux6klH1IK6`rA3}Dmu5-VMbJyEIz)=0-rL4%h&y6*>Boti z`hoYCs7Iz!d2k(sExS4BCd_DV2xJFsI0nRpaBEq1zve2a^#mU$HmiVA@N*ak`TRz> zSc?dLLn;zMuJ;^aal&^SWoZJb>?|T&SVr8>(^)>^Q;gVx{hlVHS-KeW*@k>G!z;+( zBO>krxWlUzKY+11M}AI2-g9(aEaI<)@fmW{4UNV1pqBaV&RV^Vpq1g*NnET(=lfno z%k4u~)-3xi?&CgSg3^4zgj$6UnDFf9-m{;NA29Lw@d}(=IcQ3OwIY#R(WWT`D;R1^ z$gE<<3h=+`S`LE2!ORM2Chd=cq(JUjgVcKEtl7NM!z(>D-h!t(d#&_Pc)zAq-4sXF zF|Wr{9#2))>hYAvQ?>37?qw^~gmeWcXGwRh{1mPv>Fhuz+M!>d*R7_aU{B9Z8&xqq}w-c|?bio*hMq4kFHk&F&Dgb@Xs=4j?;@Atqed zedC9=<%J$LgqOr4DcVlY93Vb8uIlZS5GQ^W1#z&Rd07Ri55*S=fXG6<&tmeHgf8(R z%brklwQ3ui>S8b1P3wcK6{Nli&C_I31&ag@DlA1a;7rFN%fgaHS=&pYP`IWdQD!4x zUb-+(66GC`ID(-65#O>U!MDe#V(4P4b`o(NtYo*%_4T$`0M&tQ2z`be*4%e+-ssk~Co7ERtd8B2an)2ld?c?eEpR)ClNW5)(;>HN>3&;y4}c0Y9U zUiZE&#IN>F5h}LgeOr3ig7l?mrHLM!^I!l% zT7r4Ud@Mc+iqL!%l#hb)QBZ-Wg|+thQBW?i{WVHR|ALU1%JAnaiAg`~0jb-PLLw`- zUK3UIEf`)hrH6xyDsy6Pr+u?aTl@M+UDsFN!4& z7g8YQbrLub#jcKl2oj*Q~eW^$$dRcK_tS%aI^G|ZB) zXvgIh7`@irofrjH`A|HH&xB{FES;jySg=oq*G=%et80`{yOQHLc_$~|%4?R3Y(>IN z|A>E&$%@2(0lJvqQfrUz>qYKbP`ptp*8+>xis(E1cr7LdnD`zE(KKXPm~G}Yf+;R*n zj2I|5oX`1>y_BV%u^(5-ygSqF+5(Rb#Yci@Oj#cO@M6dbRtjwQ(IJ{*fMRh1Y#COB zwZ06d_tviDdpl#QMzYhUo>b~qg`fCaO;|jX_h1yIh7-YbqP zS+1|g0SNYkBg9^B*>XVHfjtkIYRaRN*jX>5Uog7Ft&k+CA>~n#iLk{36q+WNr31vs zPC3PwJrk*NYgX73Ah2tPku+noc0ySJ&O7YtdqIB9E1@D$3yGzXb!T7awbLAJ-N5zu)n4>E`Y=+56lq{C7mdiLY>Ind* zscSvownw|rD}OW1ud4th0D^_6(sfN^uCC0D@jE9%mjSN0Uu@n z19!#zPvy7D^UN4d5%6M*q8=yNzP>d@3UcBt6LZ z0|lfsiLMfWJ^q>mr?1{hf%d@1M0(t1uGQl%kGpE!dry;Ka888YB~I+kdIxDuXI5Oa zo+x#uajP66cz1MiEaN1R!!DB=^p=ko#&ufid$|yn$k=(Y%6d?QbccB0EVq>C5!5vZ z09$$iY_?V4&(g(`WyK=w77JWZ%27F_x-g;=fH4;yN;mK;DRxg+`L$KAL^`Z6nPvC5 z5sS~N%a&i6gQ`vAz0;&vbwC0wjl&u=j{*rT58LZX&>>M(L~1c#Xd)XJEl?=L;bjp_ zW0u?qZ2{^r_~KU(g&oD+1r6px9#(}dEI4otzLJzPsCfb{nuUYYl0Mb;o!4KCMC!61Ep<%v=Dd&wiP6=)11z< zG$d?mp;ef;ZTGxMhcAt)_ySPt=mPuSly~Xm_!_u97hjxzu>3muOtQ4VJ@}yOq4tx~ zjZ2zmsiRLYMQ|6xHtj;}KtLZgb<1U-`v!|}cFmF~U)W<@G)yx5I+-iB9nX6nVC0P9 ztX897eLBW0S@+?qrXBJ)*kRSKTpW>@o$}>KNoEbgC6gCS+3W_Y((xy<0Li;Ek965M zT=5JKKnwCR7|6YJYa&H+qChZccOgF2Hh~cU#H`vkSB# zgyJ$Mnq%FJO>-$yAy|!FyAhrdI#><0k{rARRH~{%R=!h93Ei?aMf%a9CgcJU`qrks z2kgORs}!*m);ko!gJEQGa7osDqmr47ZL1Tu#>xAkQJ zxnG3Eb!r3jeq|IqDsv@b@Sg#KHHuua^Vt6bA;d(qO~3@r(?!}=JYDQz3!X0SHC=oF zS*H?ovo7oCqmuHDL0C*$QlzdpF>KbEY)oOGdDKbUibtJ2Y{8?>y+)nnuD{*&&aMCR zu8~<6xX$3vwR-oTAJ1j#Cyfd1lYBfMzdJcT+BrX7hFDkKnRc2$O2xu#b zbg9*+)baN(>0#DO-oC@lB2U-b4SfC# zszz1FOC zxo2%}j*n(vR+<8gPjw@Ua+>tC(b6Npm zZ#Vubd<#4ARoSJdim<={Oi&tbH@|3kclRck{qjaJL}9I}1wI<_OiowZmP&@+w6)zj z2=4{rRkmJbyDu!u{;O8%5svs* z_?Kw}x;;jk=yjW}M};otA*M`}DMZsanng4v*`6|O(j#~cs;mPPz^Rd4i0d(qDjkCG zA_h$m6C}7Sek@aBr>jD+j;vRLHS>!#G2lgo?0}ZgN!&QaPFr_Go^U2%P~O#C8Lb+R1_Ij zWaO5`(HuyKX@@rx5R8I%s%~xPG*PJ);sZcly+~(%J3l|205U7mSsKeU|4Wwf!zo1h zk4WAME+}+PvW&TCf#d1nK;TF?JXLuD)Z&JsRBe9GFVKQZ^=T#TME4b9Sp#%nG{|ji zoKtil(V}fTwr$(CJ4wg3Z6_Vuwr$(CZQHi>(&wHx-ut*8wLj{ss>Z0Qz4w}P=}9gz zfY<(FI`x}{q^sV=)>2j;)jpgZ4+t;lzfOr0&j1fNwF{@>I%M3Y{B(l@Np#L|`TS@L zCLB9pkq;x|Q{6RGpEb1aHFT>z2%h|qCXbRNRKTv@sI~O!qk!_x!k&Ioi90EN%=IUX z*w@^n@Y=Ee3yaK(S0|y1bX8XZu5_cVZAW*$G=E3n0}0`evr)mVPR+r(Tb!{;#YK45 zw#Td`e#c?}@g1-Y{6}y67C+CUCQ*1Z7AOStw;2JicuI{K_7uqx2=%h3M0L1+YBzTD z_0^RKI>8toK*k)o`0%}BQnXT>F!J$`T1!Ns=`&0C{==0D1Y1|Rjt$Y%Im^|i8%mMc zSnfiV0?{sJGS*GFFSBstFP_1Y12zW&d07}zyfnYbCefu0MSD19(t=YRN*p#POH^}Zzj!z}eojYshrY{3vD`K!FapUv^c;e2s$`Bv zN5^GcuUns-7aWtReK{%Z5v&zQnH9I3VROk;MHc4nl{dC7)gz&h9I57&+kY)wT$z3l zz^G9^9U0}OPbOl1#FkkCjqdyDvfjjhHr~pn(xYK>J@#+Ux{Z6=0v>Tu4E?NWDMB`S zLAFj5J>aAQeTyeAIJN%y&XYz|<$|UI(G{-u=}VG)>eW+gr4U*JE~!mtiv$f$#mA8r zd#Cg~mc0I3bY8WBxf`lxpje7P=WL9Q#cvb)sU!-DzH8>pc?spO5iXl*N*CnG*nos( z9M9CY{HXosHKKgi%h+YypTSb_cINeoLje;4;XEOPDkP_5Bh))2(6Sv*kDbgwZLpxD zadkcPPWwu}ym$)~Kq>NqK-QWfv z{qj$5^}b9M5}nTSkE+sftnLlI!PwBfh5hnN*Gl$uyg3LQ%4*a zg(&3G1-~;aqT-aWqkXd(AE~HYNe$fF?ompqW#8&dlCV|B!Fe%fRkGh?l5Xa+JH0Ya z^CB#5`wGT_Ud3al7eJ;Z$ zHTT}cu{0wjY$_7G*q&ocVzW5Oa%LVB%vY26!-Gx@nQbk}%G9ctH#1akEk}2O?WJnc zyH9)i7n=v*6<@p`NyGrF!&uk88rjIU1?-oiac_v|E78F}0 zC2OC}8C~9aOb#ztnl~m~iI9mEnJL3~_gasdUrNs|ig$mu0jnI-+{yq+- zmGW2LkjU>}s(Wc@t-M$XO^wP*xxMNAc|8BkUHrkE@T|q#4vSX7%^DRH*FPT* zw=HGPw-9p{yCVS24Z&O8$D!KNoZs*IQtFd)toq_z0^1qlGYuRXDAkNK^+<{cp zEA|;t!`+=blH9Fr3ieJ>XB4VHlr;^UaN+_>g@Mdj29RP(!}Wx^TUqKp)x&#QD~B== zdd^R6p78=E~Lq_k(MG4b3Xl7tSn-$9hs^fw#| zJRkv+$$+pV?D~tWB*Cz~YE(^gR z-Co(Wc*X^zfmuiFEygbt&g)z4^X)dfDCS;A&m^Ko6OKOQdQ|g2{AXZV_jZ3Xi(E~I zzHa#Jef(euTu9_P>DDj_yCm7jJtFdNas zd*2Wy6*;k&BSDJEH>I;aB9bxQ9tUwPMC~)A2i0O$I8mo1!Q?)iA?-|eTtYNfRDYHB z?8cNJ;xf_JO*m1m+CW<&2`C=v%!Iz)Bpal=g(s}dX_>8cDWhDHdH34#rdm-a|9<5^ zf*a1E*2Q99NIkR6CgBUbwkuG-N z<{*Dd@#jjszgVWM@7*tt8|@gd`HfRuT&WHGwE!o|6tAZ$rx>C6gO~%{OAP8ITP2%N zmv-j|IHW)J9_)UA6|Ftc5|E3Cf+In2f!|MsQKnrkjbRyZwVA@c^#+%nNyr}SLwYht+nblQmEI^262{HXcrUks{e<5e}%Hj*7rm=d*8?zdqp9e@tYWLVc z;Q`h&75Lb)V+e9i9#`EH<)r)qg*-{B8M*}k{pbcwf!kut4HX0>8|9yQW(mki1xNq~ zeOcFa01bAe63e7qjuncw$C5C1!y@gN@4V4Vxr$V(^ObWRq?BsvKqN7QL=_w2F~RtF zUp&ZETREgq-M8sUa{x*H`(L`?XxKQJsYRpFmwp6dpoS39x1cU6CQdK1%Cs@C+yi3} zgk0pu)S&Pu`Qha|4XM-d*In7iVZWinBPXFL;{h^cnMJv5{$ROmp$|6bW|c07CZ?qoq1UivevdpK2wdS&qb)KCMbDl!!D3ql!*9 z7TRbD%VaMDq0F5tuo^MR{?5ea8Yipa?7YSF2qI*chUJZLt9Eg}Z^q6e@m?KpEz&%X zNljMfeAY+Z`fX$N!o+vXg-F(=v$~Gg{gLjq)di^OeBZk7dG!+6yyGx@?Rw>+18~(# z)uZ$;AMXO!w73`E@jzhL0j9lCtX|@+CbSi=DO6<@H>;zo2T|*A=u9_R1ScAGSEkt) zWZe5EH7qr)XcCs2;CF`??r$}&g*${NRM{Y{Ew2g>Ix1wM%e3kMktu%C(ta~Kk`(*8$ zJL5CM3+m^MU)+4BBPRmrHBDU`-V(M>+kN{x^+meT_$hZyl$mp8@F(mz#^@oIMOl(+ z>A%~~{A^o}IGW;m>6oiVvi*2ol@`JfVGoX%PFO8x;G87$`rbq8j+dWa zI1yG+ndhi2%yv@3_Lp9Dq?uA~EYrz9IX@Do>_!Nkc)KBX8q=aMR)J0JBkqCrXOTrC zigm(kARNC_wq>QOqp&LSOZVAZT|KCg0s4(OX#)9(W1Oi}tmqJ)yuWW?_41R?78njW zXAwy3+oDlT3y**sZMA z7GR64H;u+lYbUvOa`Cp8lrC&(qQIXCKIGpjIA&p7Y;=o^SRPquZ9^1Z0qd8JiKK3nCW3qr!bE#9xuFX>#JP* zpH!Cp{Qsu1$21ZvN-2+d{xhd=Q!U`ablHDZKc&&NOqQWpLMXKmK9I4qKI5yWmu_s!@IPX#pT#bU3AO@JbELfQK!M)g3lrSESvrpq4i4h#|U>S?43` z`fl7Y4(_o4oMRiNV~B-`?|4M-GSpfk>zI9!p-^ktsN*jLTptj!^#@Qdo|%2!_6&H} zV{D9F5~FOg!-?H(34&Fqya0yIuI}&A@3QjG^%1;jxPh;BZ5r|{588s9GY>6u5SZ0I zAi{=M&yPm1v_eC4Iy<{QCRAASPbVYH_ za-uLne0^xXsWqssQ^8OgaLhxkul3gt%kKUt4`u`G)IA z@Ro6s|M{p7MX3I4P#ShSO87PI_MLmeOT1(+xBEM@du8pXEJJVHs;aYjbZCAHmCB4Q|m>AzNC3eVU zrKmt*@hD!r%hC?A$Wbz1>xG_)U1jP zIF(__1ipaGCUuLdp%PXKYq-$p zsNJMDL-%h9kZ%vldPTNA4^%Do;7zSj0ZR4$&&*F}uo6BTjdkYi5-SZSsLo~Wrg#ZT zI1hY2q1$k2^0x`hadSL*(W3rXbol%f#|C_Z&^L-T4IhW3k0Rd+7pT!eK(db$=oj}Z zgsndIcDP9nH{`(Wj#0CY@j3J5ajn;(Ms(%$NY z$!=f)%8D;DM0stVn4cG=MqPy~2aUfL!+m=yLYD!d`^H*~^i0luY1^w+;jW#P6a}V934;y4WMd|f5?Km$Sn{#C~ z-i8bjVMd#>o`I70C0%Ow?H#5Cg_RNH2h{2R?Fu{XL~W(?osjFNIeRDeUxZnQi@~X{ zK(KC26dD0g-Q2@>p=|z!Nf1X3WVGnO3HL9Cq`)(^d&uciV?~Q*B}FAgt(?dDhYdK* z;FVP8mlr^Xajeqm#6v+{evH7bd&tF-`3jb8`ji*ecOKd@a+(#Eq zCeK&cqjs>jc(!Ks_ZxIZU6Fw>A2CMmKfsbwEyIc+{2k9rk=nn(*R_KcUhe-j*PXPq zOV!n~h#cA1GH|N|Y2?h2G!=f!EM2@05*}Ckg`|!!1ln*ntMvAme!T6y-uh?X6wdEC zKD(DcB72+O3WR4l$?#OCYI!cU31co^-lZU2u97=Cetb@` zDX66f$r8sICr1M401#CeJ@Awm0>;?dU7}9tcgMIx_5v7d7zW#bhcgt&POUuCN&aQ+ zsnc~I;P0po=P1%mr-Dx+k(Fm`HJOMK=OdI$ga-|>;VT;buUiGf>-3P?N|)Oj*E}(O zFkuk+PU}7Y{jzYMz0!f|6Y`#HO?;kyd+wag^%b!j;oL({)Ocs=4$K#{zWUmS3}tJ0 zKmNR7w2LU`HTziPYJ|qfB-*9^Y>`2nadz2qT3=$iSiHq%mS8Ki>ewcRw;SAE!$YlO zi8k_1ve2^DB5)UIlAZJn1yxt^UcX89bF+loB+N$ZjQgZber?Z+cl>eUkh(2EUqT0m zNqfh-$eByZ;1}2vXOzvLQ2V+|-^x{LF_Cc=3MPHUu=1o^XPfDm}1FLwm@`|Ho~_xKtlemw9X?Jr82rj*$Qz3cJ! z%>Y!8tnH^uT47}}8M^%NB5Yj_@(PatugvZGVh>zp;Mjdi+e*Cq-6%cF3AdO>HF3fy z?25K!ekkj_`U&%TEtRlPd`dbM)oQR!^@mR}wkn*J z7QMWPzfnD`>1#X^*TKo8N&K6}X~L-dSgS#){> z!f-lYWR=^zz-lmm2)AiRZeKfJWSG)Zxmspb;WjUz3z6lSNIrf{;}WRZEAuG8hr=|z z1LE@a5iaEj9i`}p>(y3C8*7*W%*`d{gX!so3&a?ksHllFba+S^PTyM<=!CUSEL*s+P|R)`%eLCmTvM`1`0+ zpty#($fxOVLJN;q!l7>{Ho|L|!yR>S1WCsnc;XV&;xZcb6R+q+6TNLn6S(BGyDKr6^ z9|r%6!ofGLcJQtJ#PzcW3)S5%cZXE+tE^iaG{cS~w}w&AVWXq~0cZkoy^=TfZEvmp zq4?ZyT1at^6Yl83{F{AYsw8#g{_544nlU4yRi!vweeNhedbT(jm}7)dc z;aGKEz^_1k?{RK62d_aBSz?HII%MqiotZY-74c)qdSOQ{%S6(C1f+LXUC&o`;-hEP zZ39mSDBN@RitSDAC2!^mIz}jtBNWPhmN{<8nRQ^DN%oO^!HoT-*;Zl6WFBgj?++Mp z5(Ur|O%dgjlfhI-CeVgyxz3Gw50G*sbKpNMec$=-s`%6-yC&{A)x6kGKI2xIZ6NB7 zVyM}{;YOCFOa}$1Jns2H8-^O<2__i zfHG=X+l8yxvQg1wPgM#->Ye8cU3OVBPuouBIz(Q+xA~$SS)HXO`I`AKGpDymg*{EI zM}TvOjHINd+^C+LuD@P4d24>vWI5v`a!o$sW@TMaT_z6)X}h&6PGDo*TaM!M^Ip~% zQzPc**OpMDOeM`Ov%p!iOB2@U(;DG9gTxj7dWDiIWZ~9TB*c0XdPZDNzcaMquHawwZ6lz{(Sk5z^g}T};`L zB6A>cZ*zA_^dMj{wP>1O1^Ln(F^2W;l&bbM9lCgpbNxIg+WUq-efob+Fi4w|aGx#p z%3u1$9wwVyHG%gyr&Z$&c>lDe7sy$VwHT=Zll9R}>yL5(zL4b|3c_Sa6!%*sX_|%O z?m_O3vq#gCxFNFXkN2z7a4h0Yy}YpE%fAhr;@}SjY^rKy(gtIrHdyF)1L<$2+m02j zXVpzqpG3eYVvd0cfN6xOD_6LT!o?8(`2_Q5cYekod>Ni5oBdczh z^qprpE;)L;PQir!)Puqq^XGmb?1X6?zdJ13VS_^Y9rlN8qjB%vw-RpE;~@ZC1@YZs zJk@RGx3`I~QAv>PIp;h3AgrS>zML$0M{}gypENsPs<+=lM0NG`f+F54GHMaan>Jl# z@f4KEQAaGPAPC5d7D&goq3*cA(RcDDh=`NTZ?7fPiLMaJs%>RhEG*!G5gd8NC=xPF&5>t)6z}OH!Exs;e^R9lm(%=9LRJ%s zI79w{nnhgj*&Z=N`yO;3a1;dK_Pd^-_%S4|!` zOP>sYaO5ace-wfWndU`cWrv=-_f7#$Kpvr^q=!U@*MuqIva*H<{GsKYY%FH+GAsLS zxxl@-honI zl?8!^g&aog2SFqUQ8bND^@+P^HeVQ9x-_!_@%-64sOdee9i3pZ^ch_KO!}X8j+F*= z#DO|3dymxF(U3g0>Io$dcGXIeF{@q>U)tNj-Nl~*%5okcVbM%}3Z z0FM^&+J zHPkhyxokS9n{XH@hg{p^-Bi0W_iL!UE+jUXE_XF$(>J=Zql%xX40Vbyo+&ZpD}FQV76+EbJ={ZI{)+4BLV_R z4)gUCxl*uEZKN5*QszoNgDHozR1GXc5PpFId06xP^W`5VJ!K1N(C+b_tjExv#Aue9 zuE(`+jW1CUf2&FJwN=A0rhXoL&+%QGdPN~}au(g)>p>1-Zs2-om`bZ4dKSxCWp~#PO=2CJe{QLCfY4v3A z;mBOP3djlf>O|s@t_Ohu=n!o^e zci0ch%SVL?PMn8m1Y99|DhvPAk~1yCVW-{OTa&BcAe1)%8;Qid7o1MY5N8{EZUf6k zfB-3;KpzcU3optG&>gu&5R}QrVZK4jcXr3GkPD+~M?86_i?7VX?o-Y= zV1icg|&VTD!x-W}E=J+ZaM=iD<#uu5RjEM}E#|pC)Mri4--Ruxj)KDSAXKwO* zeKk6Vvg=i`2y+@@M{bdI`l55m$%ppP3wwYX75Q^D=#m`0af#Jex$nI85`|Bxm(vu1 z-;Al9Dz{KSmX%U^w0~fC>5df-07dZ>{0r01f*A}kd^L4;iR!qMXZXyOUoK`r-y~zM zxsU=z+kUvl+8m|6ELDRa3C`go{cD*JUfvPT~E2oUx8!XF*7XDS@OzaKncZFLg7RG{T ztu7aJjw!SA<#ZdhvY}NCwmrU{t8ijsnTsICc;kXvntn`6(9cL8? z6ob3lGiHg1BFOwUZqt#ie-=&Es`V% z;kDtwxz5?gaqRG);=PIanUV?&Q>02DmAR`fv64wjq{&|mR#mWGt{k$VjIBvi6(VvX zaGx}79MNcZRUOv-%#Ie@q(j-YC9z3x#)A);dz>xw>m9 zU+Q#zUE9e3@07?`i3XqI3WD%nw$`IM-opyiIE3$Q&yP1a{T-p{tQOkZ%npUVY*u=G zD5#pJ>1LbwNQm?MIyY-RTpk(gB!J?VE z6upz#bisH*WmeVf=+cos&-4#~$%5N+9J85YqzI#yh+4tM&ct}2{=S7kIduw+1QOdw zqg8V6tuc>}7y0(5QCjLIy*X=HZmXAh&*2N|wU_{Cz+BJLc+r-vhkex&kjc zo@+a3Y;b5t;ayeI3jtzt=>Ni=8`oZZfkO};LO_GeH{jU5A1OIfF0W@( z#oiqgwr{Z`m1iDqoibfVIX_x&`8hv6Rc&or@o9B7j`kMwOK~5Jpne# z6^5})O)Yuj=vh-GXtuk6RkeaFrEKzg0=V1ywp%}Y5{2T}GT+;#HUXAgah7)Us)p;N zQ>W&6f=B=0?W+l$6pwo?)@N(Eu{>iLd#EQygSnMzbMV>G<5taJ)Go;o*NnSbq))yC zK26`WNbi`8zvw!s$l#tBY{qLp_%S$gF;TUBtu9rhJx1T_*&d1i&@@1{@%o4_^reu~ zUxzuX4VDZ4)>oIVEq6F5{-}T}_Hb0FEkdonqdR017pOv7x#kSgTp8W$4 zoq1@L`mZ`eRAjiAjNgZZG{{@rCz0I3!Wq^64hF5ck#QAtf8k0e*k&8}-m%HA`{1NH z*{@-kjmW~vmYcQ1=oYdLRanjI7yA>XK{&`4rkA>4oG`D`RwYl?_I>#v$S`}?v2)lp zR|gD1Rty}q{9oW#^Hxcwk=G(}YGU?7XSb+B{r!~v^6eIQP9S^ZRG7IIf-HsMTXTCu zzxgdmsS&zLH@)68kAq3M1n`GUUBQQfR;5aw^fpYi8;uJK*w$2u_=2 zD|2pn+02x+UoYKsCg0@l90Y9fQ)B#NVwn8>ibm z9z~s#1zs~k1tYK>jEWl4;hrY&zTiFS$lpZJt?bN+sVt;Fbi~tXj8M{cPR&xKBtwBA z>rA_BQly`O>(dQbJf6w`H2G&!MXaH?G-qPSVjUbK+4^X$x>tba4Nv!{c?(eLx!*So z+$|%e1<6E!TOl&T0UqT#=D6?BM?&u~*EJdiAVMDtdnYCKdngPe{FZ~r|;q{fX$&@oe6`Y{u3 z=yXo_mR4(RFv;TeiNWLga)XIMt|t7#l)BCW8PWJHI3E$3yV9Xh_#h?us3)htI<;Lw z0Q9LxT2FWIvR((agb7A%Era~mtkdjJncPSWjmbG?fn;%lAla}Ih>jwA3g!}$t7X=R zJK=VlrOW|O?6qEbffXe4=huZ)w%jVat_j`DA6r%QzA8d=W4RJ5;iW{!%!2l7a-DH$ z^`fB12I%x+qpYMx+Vy!xnQ^xja~Z($I6+QfDXdRSbHJKb<}}TE?gM?Ie6`T=FKNJH zhUxvJ0oA$)|MFjsYSGHaAq%R;aL7)mq8>NaR6xvbljhj65ZAoi3-urt8aI}{CQxnb zUUeV~HL!sSVw>hE_8Jf@eL!gkw+Omf5(SvV-E$JC&dNcRnw9ZEYRs>D&IXLGND~p+ zicg%iobF#uW@$qN7Rjb)ryh&iJ-Sw{Hnr}RFL~3fG?n7IJbe|O2k1~Dps}8mc8q}U{ zGnG%+LElPOw*3IW3JD#6Upi`BwB$3xa;8r*X|6MrdET4?+dlj&oW_k9$P;I&kG~q!TK}H?sGVo)OGZ&j z@R1#-6%}sra}7xJ{4-{8`@#~yYTQhua?qe&VouJv2Fu~`Bs*^-IonKMam zs2AV4M9$8QR)D0YSsSxWd!t%EmvmrVJ-P`LLZ3)Ea84M(OG)$@M@&shb2?$I-h_%! z6lKVB_E4fwxtK2<&1tduE=hp_j8Knk;=tF5)MTo^B&>(&FO>YHL=6keCw;RU=;~Yg zmUDyV0qD)g;bBp9)tC-{$ku)|-!B8gjz2^;Jk|gjgK3>;DVs@S)`o_&9^rgWNqJvfWpeuB@oeI#Pm$j}h4b%uyFG9a zQ+{m|+puVTH8fa5R|+il_$Tv8o9JSN)7_HFZ)7N(_W4aqN>>~6E&2>o2^FFp;++DL zO^s*E)*s5VRJ$xa=gmkJX^q)hs75(6_cNU~WaqoF37cAw8tC2DOcxp{FH7IMXqV(| zv-SmaaIc|We`jcXTeC4omC&E6k{o6vc_lG=rW98?YLo#!lIvH5w<_$C+?akacC7!K zo)u7(sVCebyuL(d8DWl0wGudvj&Ye4K|{B-9?-{wZ&*1K7VZyr40~=4 zWFnYARv!|8^l74#vArEm!+Uz90DU*QOw@!(sndS;4zv${stO%D5ZY~F`e@oif&MRe zJHuVZqv{NlJbaNGR7als8eO>zupCQ^ky`GyAk%TRG#Z5R{U>1o1l67tqR*{HD|RrF zK0BBiK+c;}@HyTM$U%IhG}>7QOu_&nvprc5rCDefj2jp_LNyN3ma)0TxNkbL>G7Y{ zpYD(^^|~|kB{N{u4MTyDoQh^(S)BsP%WJSORvvq*wmNn@`>78u64yy zZ{AO2MGI|MxE|#h7k#|%Og1da#U{ReQnOfwFsv>o(<;^dp2-M2o0eZ7PFf zmw!I%^L!|bm_QJ1D9TPf8!8o~WCW%3h@Fa3S%OQsA4uL*?F=xn7s$DU5kD zXJf`>FcfFWK4UqNrEnJd73KjL@3#7eZXVn*NUPO+{HaZ9S%Il86e3Zq@|idcZn$Ao zQr$w<2q)*4bYzBG`4z^%Fl(KSFKGx!nWjvtv;;~X|I%z$Jjxo#UK$h%4*oX%R19e@ zp@v%+&;>}hZ|-3>?}&}zQ@{XD z=^eUN6rYVW>oW9$c^d29VLzMFyjGpoK$Rqw)pSg&QAV8U#^mz%jV@{)PYvwl2xEiy z(iR+A(C#+<@t|6eoDejJ=fZE6L2^f zAp@gZVD>R07ms$X-53^R3KKzzn~tYKK($7@d)81$FE z0zESE;a}n&TDi(-?2It*_V#uxf(;IUU=8{(c?2-jv(LzJ--`Kci))L}WnE{%Ud25H z0Zt(ZO&q}whHd$ zp8yBD{4m6F?h)zdEaqYJJQO0nPLH?qxr!Cbi(ozRpKc=lm9U>~BKhT7LyTZ5@9vVp znCdK~>nX7$2C`@NEL_+WpMd^&e?U*3nPeb|upj}iX@mj7k+}x>%}Oj`{<>P0lO9u9 z!KsuA19%hyp3ZA(6w$UdroU;0&9mGSBWQr86Y^dKH1vnF_nrcjKy$m!l43@R;Lu}h zXTIy?uZCTY^*5TrrwT?wFWS*H8*ds-4Y@Xq`nfyX(wKC(9`MEJV|es-9FGvaf^J$D z(#Su0qdWu_I}02CqA>1lzXU)oI>xWstBi{{Gwm|D0qYiTxz+k~!>ZL0_F_L*N-3fUmTxzt2|6X_Hj-~s zAj~D?4IdkP3swy&lc3MW>g5brP%H?S5j>?`?(An}S!=B|O%BQvWkQUtijqP)9a!)u zl?&?5@q!ms38vKjc=KN(y!+NDk`oNY!veqD(hX?1e$qe}Ny8G3>-mKsT6W(!>DP;{ z$ou~pa;kIx3^|}G1q|>XLyiD#>N)X@+IZAs5^I?>*asZHQYA%PJQ%YVu-zK|6x|o_ zgG$Q?58%@|4>=i#r#xazAama${Ek_q$S(5gfI#$HGh@nXwFGz_@JEt+r9S*8$+gAz z@UM7mmlPkvLlMXo3}^?Sp^*sg_zDc1L)ma#s6YoY3CNl}lW1$Y$E?TV@7H3^TS*xJ zhZ1LBBT>ALiK;<{@uR%R9jPNS1=182tE3OWMEzKDOuz&M^q#NHHrYH_5p8uzan@D{ z&wrJs2cN|2bdErhL2P`hcb-KzGznPgP|JU7HvskCEDOwX6dwo^xU+ASm$8n{$g!Ug zP^Vwa$gMoUXA)&2%dn#y4qRcvC(e`rc&qr5e+!+0_>~~Avhb^>DP2T1wE16+pv2N6 z{duDa*WUpI`ugaT1o>+_0ZydzOR&kxkMgbGC;gQI9(az(;pXw~!4EB7(lxf0SQM1V z_!;;fS6g;}t}KRdx#p4Iv_LjHH|zWN`xSbuT-omv*|@c~@=>HOFVXr6mpxDV4!EG_ z-j_HJdTVTPEDjS8hM}#ZicY6ITFZ{&m89ss+REW3+;uO3m81o!GrqP#ic`tI?^ZH` z%V4FBv3rF}H_TZk$+MS!WU5s#;K$$waz?p9iOTk4FQn^qN0ar zJPVDK4fU!%waQ2mC@3}WN@i9@{VuxY>Yo0T-@^Xqk1JU)-TY|o{)_vJljYeFegyq3 zBnRD0x|pD<9bC*h2YitOH~T?M;_0ffZs5@;&XP(;B9s3!C-~QAC+ySYT*swXKvhbF z5lZ~s(ovNdbLL?WiUJv5|5e-!@@7q5-s$!obM66X<$rWSE8WBYO(*Pa1Zlv_p^2e3 zVmt1!Q_xuY+-3ZU7xKqc1;Iw_#-1YTRZ*dDtU{-Y9VQ69AoX2;~qutMRkFbyhC+mS{20zIU} z2Zyk){)mLLr2j-hMaM@JlRaRYIy+xXMgj3d7V244-%kR{{kHpcfz}pBVH1ie;cqL9 zR3%iddf5-G7Dy&kXC>%sv2hai$|zV5mUPP2D~#gxZ0K9pUc|qPv~4Omw{#ybB_A)9 zFDqg&q@WNHa)2xmh{;W|!L>#Y;&0=zaB3B%{}Brl;1_Y7dle*=UIXAb(|W6k0J`LU z%BgfZUam&j*0+RZP2-kb!M_OmuC>YIq_!)G4;C1L5py0#=#&auac+2Oj_3{kM=eZG z@PweY2~zyc58EnT-_%nBS3%WMw%(EH zG02P1D(z%**S?G=9-#_3!*AIU(gxq|GFO7XPTBn@72+)L0z*)YxZdtRVxqIcdL{n+ zD^oBGU+XziNXb!1ml?>TV)aW;qa{%xCI_r{hCV)YKb&i|D=(yWXvK=!jU~;Eh=_D~ zT>8&ugg;`t&u+RUT*@CK#Jp))qOAr?z`R;Jcyf=S>Qj>NJ&|c$tiRedGA8;dP5p}6 z4IWh6jjr9!Hp(_F=L=(c>U0jngQnfF{j94EPRt{WHR?d3{zy>9UTM15VYbQAv8yTJ z9w15uYbi8k=P|~XqeXJqjW~MiZBY@|l;s*luDAlWEEA!C>Q!psABg#kN0IDZ_dYwf zIq7=)oLnCH7udfi?)I?t?`%EjW1I7FopgLbu>Br88_58iY55tu&r%`{VN6_A=wbCj zj;KzVe>aC$|CBP1;f=90eQlhbiRXbz@uJe;v3{s=4<`%6ng##K0kp08*Kr(1MXyVv zhxc)Ntm6H_0Bp$h_KVgJ{&Ff5r2CPwNUX5x?S8uYhDEWjhTZZtu%m7H3iV}Kon88M zR?P(~(3x>+R5cPIpV&_`(4oFoQ|@hso9qC>pYO}(Li5%f7t~+f#f-O2bCAIi3z(?u zW7lm!dNik(Kfj(nh*?L(Ec6@Z%Oug>GB{lY1_=_xptcfl7i`q)>tp`oSjS^MUb!39 z;F5zgsGax7TZxj77(4H1h(}}Kfg|hosXrX;rhEGP?UU)=+x7kF^}hS-Ci$4o>*cHc zy6gK~r+eS~`)M#7ZTbt5dwsKMe8|-`38YsCb@n1{`)0|jX`63ex!;Byboh35)eiPL zfrcnFTHCJj&{GOgJlE6&;ovY#|w@4^>}PKL(cITLx>#+i~{36oWGieBlaX$KEvRn3;@< z95-6I+yG^ZC#&1n=gF!{kCT*8VuG2K_SY!27WF)EohGJ%cj1W?QQe3rI_?;Iz@1!w zijHp>lyS$;;`h!-_mt)|PL=TFp-NsM0fUte&>MyAadCDv_w~K?3kQ;-+xq%mWKm6f zsQgD!q*+HP$o_78DbzH5?(6Aj3R7ERB);}<3ra2&2Ri6lhb*Q~FtL5l7#z1KVh_qN zs05)>1LBpmcX7MhZ5O)?w#Jbl;wSys`K@FL&*%jk{zz+@yRTmnqhZsZleAt@w_4;U zT{Jm*0^Ek7_?D;s@_%@Hr!Y~vMawd6+qSKpwr$(CxifR8ZQHhO8#`^=to+Zpr~7tS zSAF%=53%Ac-q(yd$9Qe&V;%X`cBoWGgh+)v9lYl>p0fo{@0?q$A1bmXuJS@Nm{UG+ zBv&~J%PnWdZh$s;szRa|(mQkhxF|p6IYh7Es;6@z=M5d9Io%FCy%gM+cA+Py{H+?M}kDB4-9rU|H#wNz4AC9H}vK%_xt;31wNttu0`_rR({)#&MEqW?D z1kgu~(3g)nI4=;7+AY+DBi@An(OGU{X@h(QLp4uoz+U>eQ=IJZt(l#~jz0};SGT-o znkQXH(VGYa8|&EDZcPnT?Brfi;ZBF?ARjP2Ujag!Y3Q6KqUNu35<>t>5(10cYod;g z?cA;L2eG7L5aU)=KECOT%Vbw7OY??`3MDDY!aV$)k!aJr9q550`yL!M=KjQTw0?~> zrP(YN)@8DfXK;!{JVG?$bwzX7BC!O^m|r+4Iux{2sn`s)M*O$RDYJqL*0iq7w3H4_ zb_UG!k`6XOp)54P1Yj_urh;y9-hwSaX>|hSx9Wn3@_{MW!DB#7>?XfcFA@p_EYw@V z?`O^5w}`W+p}fC13cMk}1$lWAjy1n?CB8`|YS-G8S!}WqF7Xh4Mt@E`1p_e&u+FJH zn@ygPl~o2)ErD{BI+}$CIJIjq_e+u?MJC4KYf{nf6kv_&5EW8Y8DC^cc@Gh%10iFo z_Yh=`6?vj{dgB2uh85aHj+uHlYGe7q&HHTqTU>o(Ci^3!!L>Vdk^8$c@mr)Jl>yB8 zcC%w^2MEp|eE3;l_zM?gvTNKNeH4TJ*>sf%kb-~%ls8o-fXjtMXVP`BQ3#yj4egp< z?M4Z?KYPWzL(_I_Sp1&A!EQ{*7FGmaYeC?^-P!daEEQ=U#pq?g&6GCang#djpnO(G zRL+if%6Hf^Lm_u-|-Ow&c$(SP} z343BwiuDy3GiY1;%_Y@4Ox?~zcB}Wp!PTujrhT*P?aituED?NA6|SSh$w(KbZK)Ak z3_iE-&CBjK2;V{5@&*?%xZrDW7-OGk0AOmCeN;+&W4&H1JHlkL1sEdgVkeUaMlw_e z8PD0+u2zu%s1JGhuaUVAHKRa1gLS=E-B8VekZ_e49NH=3k?A7OgO}VVIaw>dQ$BP)E>2!ZwMxEM?vJ;9 z-Yc)ZA2%DWv%S7+Le00nC*J)YkH1v}&`9iRrnEcD?{~I~oKil9#8GVAT~vIv-Ht6W zn&x7pzLdFaRCqtakE%?_%td43{~6tvKjE9fBKEt=jQkQ4iFys@98~6y7{U+?P#t+Hz!B5 zzTq>J+De6(_Ty7&I{6;4&0@8l*^T}ko#K{=B-=I7qun9VQULxe`?7beq~tPS;L;b} zZGgwEe=hz642rfS%lZT~xtM@c`80AK>!G$gQ{oQS$Yt!>J1O051L~7D``KuDyt0f0goCQSwuX)T9S>0)?sW$ zHZeR;$*h>#A2-5Jos0c9al|LTiWZMc?$H%al;W_`438E!~L+$zla&Dw~Xjw?g>+jgvmrl;9+ z^NTu%jp|$tzJSS&yy7=?-x?mI+<0Mi{uR)$kQ0_RdMiO>s1LbKy>H$aGhAl z{`8B3-8gYzgG<%;8~=k`@QZa(pyuB6!bSEw0baZDE+K&`vn7eeArollE3jNqXd4va zO(4mWKOhaUQzF_Tl&0w(B3uc-eR~0Tac~Fu821Rqz`^_Uli&kOU5@;(2h&`rJLPY~8A?j&x(1 z($2naxVMLC_6t^E{>vHYQDZ={hYloR$f@D z_cU~o^mLltwcTrUH8IIlnp1z*tpPVF3YOZsk@Zj_op7V-ds_A5B*j>|y=PHwyEtFrb=q#qBq`OYV zk|s4TQ<-(xM6JCVd7XYx+wAaR!)1N;es~;t#wr!WqR@)R_K51`CaeKb|+Q(Vff!%=OiD1PhECLkT|Sdbp4H4Wf!P^D=+n!eJaDIz4F z#eilR4CxFc<)$oDep1fAKZ!fIXoN&bJ#26T*ZFKm>suF7Ni}C?SwhmeQl=BTIstkh z3xLc7(560Q^qxJAFO(T|0ANR`f>KI6lNpvm1U1ZKIk5QakJV0R+Rs&IuNFIVHIKHA zkS^H~bzK_5^gQ-rX~2UzbPirTiuy*l8b8jP`_1JM2}1jM^yK91BRBUkr?T;^u=e|$ z)PcNKsCZQh_`cGJ1L2Z}a2x8t-}g?CV)W zriD3zmIv`l^cGhq4pL=PPY65@sO)nmHK_gEK(@emn%zbP?33aRvs);a2fYu-F;XEB zs;kWzD*=x@Z;1z#nhxU--A_k`KAMjFoUI^8> z4?Zn1tDE!oIV@rO%fMF2o3r%b2_pQG7W=CHj$55{0qZ%0W^NQaLi~b->ldpJ{E4@i zR}*MD7`LO8J189xx7ebRvuB*i1qQin6al2bMU7Nm^OXupFt6kZyrVf4UbbO8F^}#& z>h~+V?;QMffDR8VFY}y`;Ronu9LY}g!U*%`T9yob~d5rO>ihjwh(zR zQI?N@GqY-zlW{N2iXaWTN&SyCwl;+Q_L`7(UgjnEkmE>`R}+eP*glg*|45Pu}Z2h(5R(w50}UZ_8!g z0Jl-Z`lf{#^%(!v%b$GLN{*V~OJ>g)h4Rc5QAuj^Bw1XIVMh^>hajh~`mT;a92!kv zg*v(OJV3)oE_rL;_~Ty!OnDcrigm0?T5J83$Y}|IOM&_%Wc}NG!#}sNfe%2He}XR2DF1dpZ5Ml{SP3M zk70-gsT3i6mO&oU)j=fzxA8-&5E8Q4ysR9;Us1Cd_&Nh)nnatlVVg6nh_N=5>(+peac(HBGkotmYK#R4Jhq!;@ z5ld)huIH_N5peLb!V(LJ`Y6e>o(wnPv~t^^8*TfX!M8{&%dWtMxRI^MD^>vK;s~z) z^iuvE7}`sW`buPP9sFIH^DBCdGQ;XYcFpx&k}dLbP2c08Wp1Xa#q|zxH^)l271zqX zKdVk7G>8yafdW$$PU9-;+M0%Aj5LA?QUc=2@)1b!65Y2#UMCDV@Ei0_L2-`~^Ca%* z1mKqCU+T!+$)hHF+9|7Dpqk)&O^%x2_vht)9oKNkD`os)r5TV3!WqI&OkHJvBoZ>t z!%jf;NyebEq>FD5V$bwz3tufcx%)cAnLfIERRX9QdOP=7MTy0f=0IYwXk;9d+sCFy zavx+?5%m;*xTzm)Bqvf(O>8d;4Yl%CU>nWf05}$(Ocnwism?1ffhuE&YFrg&ja+LN zttrrrnhqMv8G%~Jq68tT?U)sc7Cp4gpJWR9khPhDr^~o!p&Catze@$_J}oo96N8E| z{6PFzKO>&CV$~6Ig2Nqc@Pc)Oh~f=R3RM%aHAcnH z>RuWZ87&+iJPC(CLec-kB3NCa=HaUj817JaC!>Ge3hIe*Fl)=Lf{P9Ol#VVD7Vw)N z3xacXsRHQ3p~hSP(R!YklTlth=DH$YM3}I)tXAOiAZsmtE_G^?4T(k9qKOZ7ABqLi zI?)oHn2=Tv!u%+tZyH1D)OfKo=0$lC>CFQeu9II4<|cZBR{A?Yd#$_ive5{_fCyv; z1&y@5w{UySho(&GvCdb^sQneZ;E%Im7#IL46ps z=SR1W8A*{CdWjJAh2)TL^FlE7Itia zlg=|Eh)~2POv_vLn3A;krZY^M{FK?$G3BY#(bgo`|(QWrSc@H`Mq-X@D!J;a-!E8zx`7BJZjHG-A3qHVu#pXf=l{n zdi!l-eRKay>u~u9B26xf)ygtsnB;QnxT1zNCT%i?+w?9q41lRz&j8bI4lT%v?Ti+G zK4c))KOT|%(JzSG-Vfq=yNExK-fXr}Q*XLAh5606lC9DI#D- z{RzN`@X0MYj=^M5|Lcgprcm)Y^@3%K>1W`Yf^6xIQb9&P>1>_&_s})ri0n5uiMMQN z$4&o>Mn2MGPHYayMJt+cm2b+4ElB)`)=n}?&W2}-2JuKOm}(uTl$^|zv2OsOMhFm<3$aM z51?^eOuLY5w<0OQKZB-5(9+So!*BwrbCq;VoNt8V!Ec1;8}i2-heY(6$DFO3?|we| zeN^-5Aw^J?ZrO&t6vz1ST+U-o0*>dRHzi)FfR@=%Q13OHU}1Qdu1rbusbWwkOBf34 z;XiNkZP&A=xJNs8L!fs=e+Vt{kszUo-Ao{GT|vJlGLiRdLq<^QIMBCHg z7t4oTU-y2s|2*9<(>+SJxcqeLj$$Lt`O(Vy5ygM}=}@I5@Yzu7tu(rXxn5|3{Cd(m znUx0k4qHgtJjP~@p%f`1f2ObwfXv{^n>cU)3S~c(Cp`4UG#p$sDyUQjj-?hVxVNj?}7ljP~)&`)6NBi-C9kt{9i|>|$HAEUvI0NR*W>^5VANtXK_LNS1Z}WIPRi%96=X<as7 zhP(k{qLvBLuZBB?W*USrBi5wBU$cVg8WCiyV0>s|?MM88n z%0+5LMM}$Li!^uoLik-kECVwXqz*&GaCm;>Yl!V+Q*q1{DGslwu$KOQ8R=E<_6ylN zQ>S4(bK(qe-W2{(-kGOM6W}m`yVd{Qg|KV(cLv6VD~hzDw6mHUDl#s5s{BAZ$|)+S zueCSe$!$^)aN>*huMG9`dW9?&%IQw4<4x40U$DXZL}E&qNHe-ARD&}C9@T5s=Xx4v~7_9=C;4JiB$j-8MGic3QdWX9l*0A!)pA$zaM}^c-8;y-_WBLxc}B{lh5iO3pH)s5GM5MSw?@&W z0a6{%`|j=ug>GSlwfm8&WY-7Qjt~-V{IV|;cJ8^=t)D;fk0NJvU&#VZEoqABkzgr* zw0gj0!{PRfw8_Slo95F98mH_m49oSlI{O(^n~QI&rP+(wDx17)k%8 z`O`e*m~H!g`)q#Qf8HN&ecdBW{q^hoEa7{X!`0w!g)Hp`_z=+yxM_hClK*`Ep(Lz7 zf$Ul{fwR&L)$lHQ{21Wfo+xAG-=J0hnECeb~TJMH?Ta!3r!%@U=x7DnN|Fv7t`zM5H{Nu|{Tb z$_lxQ?Us3kOx1^tWO|P9FjMcj`s(Y{<8|swP+tuD5JRnA z(`xiRdeRFo;_$Vnq?wDuWjbOX^s+bONo-437C3Fb4ii#mxVwhngN z+9m1bgKn@r;iuTXu`Qd_6`l3tEi;W8kA4*&njejAV6|G`&wH=%d>`@)-#+h`%sJn; z0_k~FUhBCaAH^RP{1xh)w~2aC2F4%5R**gXw0Vn97K{9fcQ(aq)W-}-UT1tmJG4(@^yv9tM##I-8X4BIV;#Glf)*83&&_OG-Iik)uW!|Mo+yhX z*BR%I((~u>EjrJxW|lv!GLT%q44V7XeE|_V{*dVi(&lj6MnV3a%nAzl+y}*9wNRc4d z){etoJfReRfoo#cmof_927vu!|~*K75JHrlw`li<4qrqlP=M;p{`1;V|uEXz)~`Xy&p5xghx zx1>68O0YYWnPWgDunZ$4zfi*p6JN57bg(6=$5uhwVj5IwRn6ueq_9gvnI%G(Cf$p4pa%wwL!2W75?sY^CgA07LWoP_!mt4WnDuL&iC&hS z3|cG~;M{I=TjF(kOv@R}JHp&`d4E?3Z1FsRnumyIsv-1IQT>oZnV~=AvEpvivtCh^ zL?c5Uf!$1@wkZ54kV!|lY7IHBBBk0ac(>4XRzFeW|4TMFCrzYO21DYJjV_$ z2YyUB$f7!pNf-RdKP*uN#sD{LLv#IDHXfm-w!|f}sOPIPQ`|;$H$n zDGZbMpdds3;ff}M>vBmXnyl_M^Dj^t$0ayg==W(=ado3E(A^FG={T*#R*~)FJHxR@@H~%*K2A3D~X7sy@z%lta#m|2Yar!v2Q>0@E zsgrFT6kPjgz9AHp&Iv`WFcK&cc&fN12G6{ebrMi@DY^vwuIcMb7kcz$Rv6tO!Gw70 z4nbgHjuiyG0Q_QG&FmxGlvE^d>7UMb5o^%&SmN@d({RlLyO6Fl?JClO=<)zZ-iim{ zkdO4bc{sB3ASjHqYrI2aIp`~txfGpn-2gjEUxtXFJpJPcXO!A;38laxsMYIOAt;v) zB27Wa2osQA{+u}gZn8r=VTA_zC7N);baCV${@8pO(1eR_JCVAs8fA6dI<7I|3vVK3 z!)nr(Xp}^{TJwmDGL3uh`SC(_iq`JzX-g8SSzgvf(S`A%=T! zk;JJp<))mKs;wlpX4Tf>lA_^Wj}VGFwEHi^eg1~~JA$QTQ#>bkRh)cG;C;l|jZ!k* z*Llz1Y=xH7QG0*uk2=`m<$V#bW}P+&nVgL@{bcqH{^yn1ecDQs`zYs%cIp->%BMjk z9R zSzokTu69|~;6zZ7#%=Q=z@Sm3!GT8*3$9~a*bEl!lp2C0-91t^;j@z7<1^XnrW9t>aXgx`Vpp# zU_W||U}IQ$jVcuwrVliA+q>&_Tvyf-9Hl~^40028Iqfc`eq38{;gcIpdITRn%z1fE zuDh9%_8sOaR^{2~*HM7%P93q#QF3%i5+pSpdZTn#co;hKYYYsg*1-i%Pu1!BLPjy7 zK^`4iRS=q$E_P0pL(@1{PHC{ny?(d>Yr4lGD8T)GHb;h9!*Cq!F3#1j;!&Df-fio) zCHn8}A`u$8nPxvFNmSLjXvWHtbFKS zP1*Il+fH9DmywTA`FPA0d9KIJop>{fpO~iRVlx>UfQ9gCf4d4wp`!>BjX*YJ7AN{- zP~%|6C#1NpHtM)rVW6F@tixIRTn5C&$ClKXQuFfI4=qS4I6^pDRKbO%FnpPyj}K+c zI~$x~qax@+m9?k(B67|~daUGpp{z_EkKAsK$(f|la=tb_9~VFc^3D8ex<73VsWyB3 zQt-Z_k+OnPzHL7~aE*{oe2G}>{J_@|PHwk@X8f)nCog{LcO0u--<#gzp5XxQgBbo* z1pwx*7f<2<;dS{Pz_c}RH^5+4sraMfPe|-z&H^;k1o3STkSAoo;tCwpnvV|2vT%mg zOv(rtloy2b;M7#xO=j4ZYn}Q|%AP@RUQUlP>^?(beys=4GpiS($AEi#(V0SPQMkxN zuN&OF>~c+OcRizg`%bGYfYNGTDaSL}J?>AN_nu!V*Saqs^zifEUuHRLMJ*pQVD+my zk{FM3o|>tiztz*whhI!+8GnQp0}86+p%18W==HfMgRp+ww9snFQ`o z!3VYkzb;Tg8vb>+&0_*@U&5J!36EXpSD>4qL`C$Bn85OBx6hhGjfe+Ccf}k^#eH5H ztmGqbrYy~MW~HDY^+&b6ZW?HmmRDvr>3Keoh{x|_nWqLT$IwEd^oIv#Za&L{? z%IP9Je|S*z{eoDech4CD8iCx?F28UryHhTvKWQ|X45d)zbf`XCRqm=sB3_ptR=jLT z35?JbabH!mZg4sM4Y9G}`B3cxvfwo-QuSv;*jxe5tid@6;iI~Cr*^Sh!iI7OTJa@p zO*@h*Ki9$Owav5Qf084!*>GQN4VCwwQk7Qv629gvq3Kq;j7~~XuZjrI;=KGvkWA#9 z<;q{4vEJ%y*xL$)tNf;gm_Z3lDYDV%V7XL*^>M%N;YIi6*-_bTi_!7cNvNACF?u9A z3HuupMDO6KNfrk6B}X{$I1(-5+%hm6woX1kwUqR9?LUNGjAn?Xd_Kn09A?v zwwiZ+NyZMij)xjU+cGbOsIipU6>l+JVOjN~qU=~g6CX0ge%`hBd8&G;wET;fx3q5^ z-xhEpo24dyKA`WNi8xAcc+a}1hrynTS*a8SGn-4E5U@zj`p=LdMmtyw_%ATZ$Y8^# zLiSOa$w3#PxvnE$DgTm@JFBP9 znS@K3pnC#IFd**Vkq@7-Cy_;Dk_hN}{O>fz7?f>4Jn6?Hg+j5opRX2-c8SI;v|p?xY@2-(B9$E-}0#eBJvHfrRU)g9--p!<|kV!&+jwaY4T4PlYi$=ajJR8NTIC zQH+-+#8OaO01jV}dcQ@+=Z^4?k4upG^F_F%jFjgJpm-B0udiQ|G(a?0dGz_AyQn^r5Zg)hwa{6OUFnxLG9YJ=tSw2=|%)NQ~#1;H)c(O+K-j zOX92D7L}fX=`3ODemur;^#j`SLJmxE0-OlxE@=@#qS=MLNJL zYGvK5J+eIauMC_g3wZH@SLxl-flA_YxwVb)^_$z7KAcY_lu(S5g=ZKItk4d14>~Gp z`7CU=#I3ylrNfwT&H3LB|34hY%`Rn>z1O&W6&>I@KP|4)H&8b$6D*8hRO_;vSx?=PPGU;2w*@xDxHs==Ek?c9<{?ntU&dSv$u zS-G~KsWffz+v`o&>>Ti)0g)4rfXNoAejLVTe9zgR-XH#9BQa__2jc=tP?e}*2jOfo zgzA0rT7ssi%&GwOKoy32|IJ@K_>4L{Ol>xGl!T{yT6c@ay|iXk6x#pJT6I>;Q6BBV zlYQr2UauNc!ku02;%85C% zZ06B@mdGG(Witx9-KI_XZ3$YSUNLV_iS9UJ>}nd{5gkSW>SxRe3W+3T2IB?cyuQcg>Ktpou3q-}P6cgeYY}d9^8OZ-;fUScw@3Y1B;(!s5mftv=(j}$^v5ls z1r^iTr_;hEpv9KxqXbS_f97TjwE{;1E*@hqweJb7W~S zXIeNQa)(bn0o<2FQg*P1j>!)eh-5G?y}(n5c*+RAPDh?bhJ-LvNsn&1rU`y4rUnR@ z1r>v(9O=_RB_0@HkyD``d?9fcYpkR)lEgV|&NVi@^IB;gked?pLN@IgaWxy`2^0E& zq}&0<)dHBmUtRd|{i$J+4H+#l`RVrK?;c1d7I3(=b=L}cYvZ2U`hxSEXcU5L%gI}T z*?$)=<~$Z$30V^Vis!%K5eHh+m z0-DDff<8=4u`w%~li%B3d+9GFq3j10)E>#bBx)fqiXI675%eQ(#F!RR`(P-Im*Ct| zxs7#sM3*sp6?}dDXO6qrJxiK$A5lOMl++vy$3op`eXX&=@{=M3%CxF&y1&P1Ket4p z8~+|e;MYIMKag#_0`I(ts&$D$m)iKvW;L}fdq8FIX2MJ>cKBl=5!X56aiL)Bu2bT! zblQ7WgQ7c0PAwLXb7PuUPMMlL`6EJ(C=Ec}rx;x9+M;{DP(gScwzbdMDX-1**js2n)y~-21v0 z3JSq{1$kbmaWMhVY_#R|eKCQy!KW1p!cS;HL#lzC8WOV4TJS6r51hn zu|zyLy7I}ewydWqx+F1?$zql|ZmO-?vJ7oH-q+sxKQj9aemIz&N1YVO9NOYd{6X(T zO3-R|s`$-x^@$gFprLKM8y+Qhf8p}}9@{)CwxqQ8*vl69m1S7I6dc^GafZY`iX`WD$b8dljlw-@1f$4&-ncipR~WmERI zmvQ0z8c1NhA5>}d3xDwGKVY+XCf0A6T{xJ+l`_VXp49TVmT5!Ns8Z)&-|RP~V(9OAkq9runiw>vtwf?r0nsPB*BM99y5HSi z6C@)j_0!E0eFQt6aQ%w=0AHeV3{grYUB^bsG9-9+4WS|I{*Ae&t>iSpSjk|RyJOFL z%=e_2>^bbKO?rPN-D34`L|HzgiO0)81R=RPW$mU|sChVG_z+~Ri8|u)8&m3*R!98x zWn>xFm~4ipVwo1I@17m2!L9sOkV4{*CLu~UGCL*!FQ&)#;^v>)`IEP^b7}HTq1cg8 zLZ(+ZM!yJB8zhIsKD5%RkQwptgVqPA{hk{_p@cVm!ka&-J;Cf(uj++vQ|OEnd2N_u zA+&m3cN@>Rvzu<;e(n6iIHRz>-K9@gFzJNWxuSy%&MYa1QlEPbN40TVHy${_Dtt78 zSC`2Ipb7XBw{baTjI5zqSEO&>2~vw-d|^nUmBX+semvWsQ3R6sb-js zI7Bw!<>UZ{TXJW1J0sPk+?#&?bAW6n2@}Q09F!>CmPO*kJ`n7~qr}dWv`Yd!y;vb- zc6(BTt^?yEpE{(psm640UzNLD^T-7DaUy!AaMZD%;})`JX*kSz<}aoVS2_OK*_<1z zi%bxP>yWmb)#BCt50Z+==y-_gTmW$%cQ2q}Lor`Weud!QNGjC;J}GpmWYmaSEgJj( zqEh{l1Q^zKr`YVRDO}~zIb2cgLOQMOH%{K%7p38?pwsd-fh%W=dX`NvTmpn_WP!7q z<%S|@aF?8WO#YUVenSWo4GzqcUJbf$G_)9Yyj4y7=aDH)w z^i|yscp=|k{EO{$NumUWj}!(SA#v8v8i(d^)w2P!qHgp|N zAtp^@g-DUsWiV;LE|na~83iJ_p5~r6*|#5J<_4f0ozN$Ep05f+nF<5y%iRoqQT_`e z3V_gHxvk9@&SsuxN(&zmINnp4Z1rVDc7q%~k!c?7!pt^RBp$5K>Ut^aE_$NRx+v** zgC<{A4yExbOH1lJv5aym7MdOlEqtPt@q||ko>HYasHlD|4*?$%H`GU}aUUhwZwLhN zQ3PR33b0c|LvP~okH5I%1_3bo_pHpUx}aG4O2B|?rqc^zb?WGO%d}&5Puh+hlRPba z@pCCc@Hv^IT$+P5crkdrIPxgY-o|nY;DIk9+DaMh?0b^JP3dIPpFTe@h-C`Lv1y}k z_}>V~b8LXfEOO{SKTIr zjugm$s4*^2KhzkmXDpZajxX1hUoBrV9ipZ>J6u6RD`%U2zT7EgIV@z2a(B1hA6Ex2 z=EooIn1(toX6qI}l&HkmER!1dX%!+i8C$mc-{_L`z6OAG!GkQG(sR^*hBozk zjjr6iv|L4?aL}7^c|^J{2KrefH$Y>A*&@{(#gXlv!ie1xlSD$%9b+b$BY3y0@w6Z! z!Di4_b#U@=_jfq<2yPua_M2DcQoOprM%2M;mH0dgN?-R~XR{adT@^DL=`}Vg z3Am~<6sfQf#3~FVVFP=|Ndg8|Yq{Vk>hR#BNYfS9(;K#29(7ACbFbJfG|idp9aE>l z)>bUHN-bZ}k4VyEb1cZfGwC)l5>dsrrF{83Zg^H$UU3S;fyw}uUu0j9iZs__`Y+3Er zFE1zm(04xB?E)4sE7ha_AArS~DeM#|C-Ju9*|>93t{=u$#VdchMlF_?NV=`O?McJl zAe@y7^4U0+gVi)jX!3D|2*;k@u3jr|#phVP_uzG}}+!>-j0)s_BI(Dc2rA|65s~W10Yrfo8o1nT)o^a$2b|1z9 ziK@P+1Yu2b=O;c|%p7;_7Xu*k{kzXlK@q{jcluu>iy<#dV5i~alP^LUd|FFiRywEF%j%NJPI#4^A zy4^jU=6TJuF$7o$RhVSC>>;nfu+DcgndE&tJntxJ1p%P4V49Sx{HVJy%?TMGlG(?7 z?LxUOa-W&!kh~3Vy@FaggK<0w_y2#RE0Q&F`SmKXBrA}qK&$ej$4fRlG5rj0u&Mq! zjPqXVWGosGZjJB|v+~5Jh1Qgl9I^zcK|EtMoSB5$hwF@c>8 zm?LNjX4DuV7zCOugchal>o*3cmJN)n?-ri+K`F_NTmAVMe}p{>41obaxAIOjo8 z-g4M`yg$bar$|^4r_BD)4^FTUNf-l7I30?|XS@HE$H5dP?a=8sQvV8BLi6F_$o*GO zB0pz26fT@0+9|B$<^M(}$h7{0PU!RU80xCjlA8zxpdx{BwQsmHuRB=%o#W_QbMdG2 zJbb~Ka%?4%^aI%!nIM>UBLQ(Jw#Sj0dqy;l2~wu>&@XOyMlxP6Xr*D$@*$Ob*5%SSx1ePc%+5*!ppg_?D=pmKo zR)OQ5`TUSXnh#m6-`vTYksnUyS)rQ_Ioi3D0ryw%8)dV;x0#}l!tM6?PujtWNx)mS z`x)l_2&AiXn^C%pSSYDwVTK73;RccJmJUrG%ABC|)9D5bU14YRiWs{m=S4IQ1yjlb zy&+ws>Y|ju$W+RK8E`Z@`uc!c=!!tZZ}qf+-XSpR5`H;x&Nhsf;w*A@H&e(N9hff5 zJK#A+stY%4{OF4*IQ>2G91LP|@bG0N{Q?38Ub+>k`U%mPWG_go$vZg;BwM_Fc4h)2yuO(^H{`a^UPG{CLwexY0uF1LfF2im2flJ0t zJnWP&yj!;HRKp&X%mD0BRLHjqF>8!dtGE!NXTe#PUgMScy0fc%M}b8QNm1AB!Q?EO zD|*{1Ci19BOxNq6Nvs}nNa*_5LD6= zkX}hTjd9!Qfc;|bMeDM8a({50Q#U#>pym_DB=I>~F-LN7+!uGpVM>9{VZPSz) zc@T7$c6^{IQQZLZvU6ZMon+vmK-l!4tmQtb`ec4-%}e^J1lDq4%}}R%0+M%l+oP{0 zGdNrxFF3At-?=U@{C+e0prKzc(6+8RPjh_*^l}2^?g_Z#rMz~9s}PnF2;}66SN?>f z32D_QG(&ACJ+#CP^6>G|4E;AgPUxP&*85VD0g=cT* zzPF;@yM;GMdSGV@yx~lA1#0uZg?I()!siq+tB+#4)Ug8sOEA`+|3eta{O^PTmS?PZ zoL?egk^U@GkP@R7dT?u@=dx`VP-k_htoqNr)&n#aXrFk~dZEwQ?Nz#=!wjP^jVPtf zk!L!}87(_H%3TqbZts;k%J}>>+Iest3UmYZ8M|_l23t%eEt9v^oru}?(vO7?ROLUE zfwO>rQwI2#H-z0%E%!+94R`)8#(-0|Nyv20T#+LY6&E{E=J=sIy-SW}y?`7x4v1si z&3%`#!iKq4b6ykZyE9pcMNpu^_D%=eH>4L2@Wu^f>$iRTGF#FinlpdnCq<}@pw7AZ zj&{>OYkw?fpuj^AFSWva=Wu0Dx{b#2RfwLlofp0kGUl!cCa9K@RxkEJc)6B^S z9K5A;>w1ChpuKT00@U->Om%#Rpb+6|xD9cQC^XlO@kB6l-m|ho&KbH@z^e?i^3`>Z z$EwIAkesZi-I~1CFAc2+^g%=mAyo2BKdLcrl;gLUin4q~uv*fapYi>Nr1cPs6A;;0 z^t^i$L(OMxV>M`jh&scLujr0v^%Xt7v%z{;ToeSHpKnuhLYsz43sbH7YN@x|_hXLS z_Y6e$+xs^7&btTS%TbTm-dojA`v_m{r&*gBL%YTjPV8Q5HGs$ZEso#m#cY)#JsIBP zCP&V-#hY`tAiw4Idcmb#d$-DgB?%`d$Lq~r_Bk7^+_$FU4hr4l`oIFuhl+5C13dzt z^afR(xtr-tFcB`XEnJX}Amm2*5Zl9_M1TT`gyTROWr4kAJaHn_U{)Lz7c`YZ7n3e6 zZYG(F41qCKbUqcKBgoq>%-iLnEBO+BDBzn_EiBlfRl1lK-0(mpkd=&~10I-5TgPu0 zH7gu(3g~WE69ud7ivX1&fMJ3AaH_->|o=k^UK|*ykk}ArQ zUj0IOu04t#cPO!cd(6DJpGnbnXTi^7?4u%D(VZ*4v;0F65G=Xr3&<2?#)C4}oaOQRiXbAD+H zi`a@jRKk1z#@v+$&<3)#LKtgp^d8Ky@*cbcE9#4$ft#kl?+=KTlQVdEgKTEDov;@* z{p-FxZgqgGppom*oONSmW6iV88)RhG7Z*DyZ46NiUBpCbq%DfWH?m8+ua~!icir?= zg*_pjAiiS8spyqVEX}Bs7XotNJv)SFwqlVUYB~%5O$<(f0UxM_G(>$JS1NNJefCPG zPMIavFl%uf_Sin%N^xH%g{cgpYOhze6ha!tpq4kC`8hIvUQYctn8qJu~@-5W)R4%8>>6rpuul``O@0r6+$AfGpE8gLe-IV^Ne$Rx)-wT8 z0!~o)tu`0Q^7o&TQ9}GbB_n(Bn+^p@CQHL@xdA4ZXN1{rd0)Lk=<{hEMd#ZTiIbw~ zZu}xPTny|Wz|#|K{yMf}XtNgQ&;&QHx8ZcqFzs4W?sqaB<<- zaUem-5Z3nmHni$H6BP7Z3=dYwVwmL2ahiwtI_p5|<6W9xILtJ|tjy`sqPBufIG0U? zQQICyFY|#uOg9FzDDjc0$8D7f4`NDA4 zwRkzT?Ffguc4I*;>U_^V#TJEQV(=}hdaKnM3p)|{os*bf+&GOc#sqpJg!c@w%fH0u-?ksbh(f%EOQYS2N>9L=YJ0h6+L4i!_1gSY^w9RUmL;V^Z2u`-=i|$ zdZR+mlt=>ZM*q7j_M0vGnxjMdR%?4~U*~BER+{)%WD4(a4S zAN#q>cicc;cxp^YGaPCvwROs*0dL!F^GaVOi|2O#ak5Lk|Nd-^uhe|ZQ|7>w=Z6{Q z0j@l^l6n2;IcvfF-`gLFir9-MpYBay#S5a$67w1}_* zD0PAj8Y_N_xZi*q_MF?QZ!I5E+BWNdm$K>IYX^TPn7ASiH_HPB3DQBmQu5cvRo5=r znDt3iu6~!ctYS6!3@SY=di`_en$`YCV0_g}V$eoCcJiS01Bt&-o(H!6E$#B~Vs|Qzo-Z=?p}(wK@&1^cCBng*Wxeqm0=jj9qC3DS_X93i-F!>q z%aCxJ^P;EScno}WMTrnE^vmDgoCCSitd%@XGvz_!H}`9+dZlg3|hCtS=A*e4gk zlxa1GcN=7zAl()ue4~+c8upgJV4@Pte({TkjBmMf5FHH73Dg@4Brv28qv`-cwNGo0x=()*rsT+>6=##-QW>;;#x@^i_?~ z4ok4Ur~TM%zD^)md3X~d%hlzw%m~7BqYUJhBPt$Nd=~zL!%`UXt!Ck_Qf`L$$zs)v zMhd>pAF}Kn*0#}IJWdnMz8n0L8&FcM?AccywTmjT!c_lH8LhT@`A=Zn`rDK@3?Jn@ zxsfZ`nG%AA|SZh)!)N>T%xxc#9npx(SHl#a3#a8~^y_o@-MAkF{pr2qd}Zd-dNF za{qP{$_2|Ii|~Ak>aJ0_hA(GO+=)(562Tt}q7?VqQo@^bvK!1j2W!&9kqVol@{+O~ z5&6h(I%~~-9GQIadGS)s`bU%N(EJu8$S`(tElPKvc;uFj^6 zuu9?Y-+adzJ4F0R*<_LrIQFnlZyP&7ak>=G5c>KEuIyvaIGK|SXl0eKbc|u!G@yQs znda}t1p}yoD_)j#UZJZ9MX+exHALBIipj)EWuDK-l6=y!Ykmz;0Z0(`quZHyVg>pE zYOHA$HUrFoHuz9BQ}6ouHf~ls+>G?B+k9}B;Ef`9Fc1yfX8-7C+F@tZp|SKN_3n7U zX2Bn=U6@vXU9h^{!O|Ub^3ZCiK$`(Iida_VD_M&JC66t4Prf))9U$SLm*+Wi6q$$r ztMRM#^OzA>`LE$EW@-|OKFBK8+v71sf0UCiLw?W$CE{2}#*Tkh?NUp@*q=0qp2bzI z+`7**_p+S3FtZ79xibR&M0$S>JB#LmFpOk%L&!zan$c)-=s%UV6HTWlEpYB5)3@g0 zZ}CyrPBtRkLLsw1FHhUkc2(jer^6WMvSCB3+eX3UW+^6#pnjpT$t&IkagP#VHeY}+ zOR>7|?&x;srjU4-&82yk?< z33ULO?|jxMIy#Wn>pzUsfpE?qepdYJgHG46A9Di5Sk*m!0*9AIlK236Nn)(ByvavB z^q4nPJ>rGCGN#n|L##R7*vDzTywLAjItKpFDW9_3OGUctBDK;=QkRApH$zTM@bi25>1Js0<l@kRwsA(T#=4|Gh14K{UEcr5Z{^u{}N`K$JE z6&SO`kM@e&6gYJbTLD4$=_c`CC+hG-kcMtCA^VlvUmS|mTBwsX_wKat`P8Mpg(C|g zFcurSyqlStnVK!~4*v-a2n7`O#@8h?8#-kD@6^RwqW-w z-5GIQ2_Mw1fN~Qr66l8@dU2qSY54;4-FxibnOzM38+`X_QbI=pq)P114g9*g|Mp*i*mh5iho%Ox} z)ZFNzi*|<)6i5`lK?BdO)s&cWxA-!IBHAznA_y$rakJNsoY}-!MO@*I=Li+9RkLuh7h4|oco+po{;uFZ}0;Pqluo~&G zyK5&$U8ko+9Ig2|0{LNl{b|&GnyMLSiGOq1h9>pJJ(!A^PH@;$m<_Q_gL)A}y*|`% zDysBNhHy}r-GcydDA(mW9#mEQPQk!Jm^*K?QgSPh$4l4IWDBM+?}cjEhQ!4JLSPY zFb1`?reUTN>cBrF5w-3*2Kpb=>`8Jt)8IDg+iB}O7h8=ltBUMK`$1DLxUS(aA)UNO z-kb4Oq_xZ!=pa|rwQ`0tm^DzCO&8QabfLefg18fy`)>?YG!WP9gdTN!&MpDx)3eKO zyI+4GP+zm0UxNvMo!f#hq@36(v6v#FzcoiMrJ?&eEzy_RC$rFSX^WI$F-pJ9WJeHp zaDOWmb*iD4>=-!OR<+Q5s#V=W91XN}lNwl>57DL7iU?DC8ixNs(HQxL!_qBvpPQXV z)K~}os7PopNdOrd)iuigY%8{EPXMgRnRQ~n5Yfmc#E;EH_d#(}?t>4rgmH532n?ts zlz3z%+tbAivimFsP~eLx-qaiA?c*Lco4Eve4wAjY;<%vb-x@H8_vFj%^!t}Q?dM#4 z{^^VH`CKRx`4X_r9xIaC&=RnH)`KPDeB!Y2s-Lua_{|hXVvzqxFK;JE%27MCB5eP0 z%SHh?Ewpv%Q!*ME;6(Q zF%$Ud3KFnIJ>-7w4m<k5L?{g;$=YoWrpZ{i^n0i_*RHX*E$j80rTr64(IXbZ^(#vVKfVY15j_*3U;H=M4N%Q0N2o_OP#jm^I{kLRB$&i zaL|M@qYw{kf&&6DVB4FCKvp+Mqbp%mftr5xKlS<#Q#|!iTI7V@an9S+j4Intgz`r3 zkAmSx=f&ulAFF4^9>~dF`U8I(f>c~U1>J~)HMWohx>=)cXPWdeP2)Ckm&I|Rg~{Sk zQLHX4>kdA*L{(Swgt!_JG2`p#sN8!G# z`~cQaSg4o>H{VVttm*6t#2+;=YxUYb;f;N_vmjMSjeqr|4L|ty`LNHr;zq`--u$Cf z#vG~(We#+pko4{2i8ngM)VKGzQZqjGc*m}HDspkbJRG=mZ<_|3vBnG@hN+l5t^U_( z7;pij7j7EVvf(6TueSo9PmU5Z z0p8+-=NUTBn%hQyk4Me#g@)d7+T%=(3b-}NM@AtB6koO@!UPzncpZr|bSAx*2Hn4p z9F%FYScWcGT16!o7Sz+2^ZXLe&I*rcHS!fmga3HBW|$9`)eh3QYUxM+GaQ186}Z34DAz1UPDYX3HCJYMvu62Rk`8J zn|JN#pT78-*mGKxw}6U;42mWTQzI*4zY=~q%~GQhwT#6+u<)YFNrYQ6i87{pyr6++ zEKBiN^v?J3i5^(Oc6#5rvI7UAEpv(zKIEq{^j7-OJKb%?Dt+hl5;1fPQISRFwzl_n zb6D*m0>uKy)~ORxMwkxm%|`c zj=j$$b6+tFyP_2(0T`Ywm95W(?w^3dpaHD;=Hp*Nig#~?#6d{TJaNOUM~0yt;qcD zMRrK}wcL{It3DHJ#-|86S4xD3`Ism6W%{X%>fk+ESwt%0Jjb=@ImkAC)5irAVqK~0 zIXa6=Bb2{+XlX^*gSA)JN2omWXhEVvM0dOF;zU-X;C1IHKjOw`XJN4Z8VQ&&>3j6O zSIM6~4NKZhe#<}xii}HUo(&woJ#R@lj$eeNe({j~jd&PHnlP)fvIEO80&6LWrCgo! z80EP1bL>Wle;s&t_I0!r^U6q)SyhUcj!iAOQ|MKTGZPo zRn%;EWz#vWMOHDR02EQm?{X_u7c4zR!}@66G5?EV9_Dx(`=NVy_kUjC!hBe(BZfr( z5z--J5?G5=L|8TAzl(OSw|tF$;Ulb?e=%5)|Lv_&{jgsBng;ZUbCI~wr7sx&4SO$U z$NWN7RyZw=Vq3svK^I{ulMG*w9=_+* z?bk6V-a=JQ5;?5&Sy>z|L9D&+=%0{<7|Sf2+*ky7HW-z>p5E9IaLke`J+)#1u5Iu` z_q5nJC8tOA@9JDg*iA)_f>_vnm&*Vez&i_evfX{L>tA8*@h_ABjV$2zpwygO1k+O; zXe3;O8KNmP3`R5!$E>oLq_;NLqpAHr&R*#LaEEtI{ZAbWD{P+8Bl|>bfFus}PwWS2 z>}9>zJi-j_Ffos*0;R!wFV)Xsj-Zc{kcZN*vZ9!MS)zI9@mSyt!QfU}AdZALz3v|@ z7pcr$@D?1&u`+L)atceVCu^;Gmh0gibRL7)Sb9#M$tyP`=UzGM#n?*`Nn&VA`QB5b zEdJZ`Bs8Zn<*d#76AAX>Lgx&$!3B^K2>%l^?UHu@BtZEs{!aqbEUipJCKFFPuo;4o z7yJ2H(Uh^j9}jGJ;$Ul^7nIx-ehzi}=Z9-z)cT@pJGK!c_$uK1*9azQMGPx&n)}EmdFxO!?OLvN^*B)F+o-naH zE5CD+@d0RBKfInodquJ8lO~1|He{kbkIcs#o4Favx6ouW;A!3EbvW>fiEH2Yis?C} zJIC@;dwgr$<@JAha{}m$KYy*gEzFcnCX=-6rm2pWDO?~p$2-;a=!o~T_*T+k*mmGr zSwa24w8gTsaZd`K2m39zW?fOS-e4<#sAl1h@_>Ev2{f-img*y5hDz7N8|x&Hq9S+B z=BVwBBe?lH_$5(ou3Ix_@{7Z0oB@x(D$OmFK-KZy=F^l|z-bj^ng3P_%}~j-3o&Jf z(b12|zN?Byq9&+~B34TQZes{-U@QCH`xDvoV^q^_O7S`C>6*S7Y zIc6i1{2Y6i)mt(B)4d41=Aq~ps811QIj10w%uh}sfu?4#+v8BUIxT!zl|Z7zDQZR^2ni`T8`+!Nmih^~gj>x0s7ihjBV@tJ$wS%KQ!1T6uCPJf}aaL1v36@r;*%%U=bPc1K* ziL0~t;Wd=;6|Y*2H{oG4+{d=r<}cXW0t+b&!Xx`{nan$fP7@<{(qaHAz&f7o|zavm{a}80&-aPy@2p_rDo-8%9 z55I}+3ZhMtA9ZPc^BFp&w5cVSJ^LKfuR@q!PpCGvMAEEc-ebNh~=* zJw7QBVdVwku%U^nt2P8*^0Co)@X2dbv66G&Tu$MIlS$~mQvr6XI4YXNKq@=hvM9kQ zIWyT`88hH;_nbXEVe{eV=2n$yKx5u;%K{fO7IlaICBO1`FfR=>VBm}upkKlVDA9fV zr0zAF`ded3m>4OYiqs%nCL*+c6wEJhGVBEoITS8G^CJqGhgJSAlE6NDSaMLTu8(Uw zRFslZX^xWcLHvtkNVE{xr9B#Ct@BuMjlAE@q9aBt;bP}tbI zs?t_wc-9-sr?!3|+wQgYt7HWnnG{qe9?LRYKEq#}gl7UBkQBz7s(l`))$A&rU^Uyo zg(911zSP^;+n8DXY%3s^{%%+$ulHJF&{*Qkj*Hc!$?%pZ>gw*k8WA%z*P^5q9*Tj0 zuz$u5m^HSG3|tf^9#ip!76>mc#EdaX1wmL=1`f0D(OmrNm1t@9IQ|i(fnL_EYom;G zp3}J8>aBBUpkV~!1IW5_-WxxHD^eK+HeX{z6Zf9)I`N>eW{t+w3{0KJ(W46l>;%OjlOaprRJ%}xz=1#GvrR#@BR%e| z!`~6A8U?>RCu{HNFvJ_o>yv3-omrM-Nj5#drPUNzGvGH4Uz@Sv$<`5&P64Ce0z)I` z8;{9ZVPsDS%b}6MHu!n33yz(}zK3h}@qlS=hF{C?(mD&~IR9yP@N0A}) zPg4ZBxUZ7z*SkZRB_@MT09ECOF@fK0VcrzPtqyLt)o{tLYszk7FJq5xss`~AenqRN zr}ucDoGWm-m3Ucn-lS>yiS$SUT+tD+@U7}!9qJ6oiT@VVoA`Ew1%Wtw;7z#nQvIhd zPQ#z1PZ}c^j|RlVjd&oK`w1us%cNY>fUfV?NICtU)jKiq--P4wJ+f?`e@z|LX}|8C z*o3$cKhZlG3lMYOVv>LAb%oXD#yFtbr-^{w#>>Z-p)fh`n30|C9?}}>{w(XwfHjJ8 zz8Fwjjd4ZniSU+ZkXEuSL@5VqD8uMC_xUklJkc~*x%?Bn3^z@r3O0nfjSB-`n&WQH zRg#)w?q~Jq=B1+ycMW5f+3PPPnOWQnx;|z|wVY9(pHhvNgt)h17s?^0N`ysZ=Pofc zZLp+O_?ylkC&fGcmO+sTZn8g_WbENX38AyWd*9Gd`(qD(xeR)ZOHC0=3tybn{{-U* z=*9KNtZM5yG~{Fh*&UjP)rIksITQ7u&JiVTmU6|*-bwPsgo8+j51f==38(c_Ang*r zsdqN9^@(b_n^YdGN7o16S%F0&kb!Zo&UO5#a@3x=Tr`p2m+~__qGmItzbGI5!DY;d zIpj-``zm~r#odB3_=D8vS=nXumvb7=9NJ@~m$COOlE^f|(Y1}~9PEP$xQB z5OeK)BwOR2?(=i5n`d{W3*h-!+3NE4X#eZ_yh@IcfxP|CTYRddbJfIWy#>20o<_aO z$)oe_7TQs(=zMdC_v;j0)5QJb3H*8h{CDThYaFS2|HAZ;*(OY3=T+$ggbAI$U6X0_ z3lT3M-EOAxQobB>)LCg0A^t+?60K91ffmtbE+yj2Pv5?S->|Po-aQrSk+lvP4z&5z zC3|f%4%B^Dm&?08)=f9|0BUv|YOU!B-qvcsbx(FXx4WD|*g8*r{s)L!3D%^zznf;) z46Pm=Dawj#q;58;;Gvm6_hCV9BwM?CvM+Uy61+p+aOj&nn7OzbOiIg|UURt8S)NYe zDB?s%oA;ossgNq7UUp9hl_ymXU_Ufc5POM5-0A8;j%Jk9(%vW+rpFYeY z{$6ZN>%jf`UHS;kxHhWUJMjK`bu1nFo6VaQv=sXLvRC_yr~h0%ItK31TmBwZ@9iCX zsHZT0gX9L%arFuF4B=T$aYN#M>fQxcdQ6;2e7*mX@HyOgmKnR`QMji(-dOcS612Qb zdEg`JuqCS_gp{X+zZc@RIM-O-CHct{UuSE_It8Wp{c;;d5egviKg5!4Hbg~#) zS0&8T1r5=6r!cePZtimvGeqar5U<~oN^#o8apL9jl|RU{Iyt8L&amNS)4MVf^P=ci zr1DW3C7Xs9Xwfj3jSIR(3`G#l!-gEkczigoYQCBYNJms)91Ri}GtFgtuP!&28^GIO zM_Sy5n(`A8kg42c;19d_k64KLGCWW_j>^Ktp+~x^Nuq@g3L$9uhYV`BGmj)DZwTHB zYq7(`pKJ^f$olIdu@pXSHHjxvab2hqt55Nd=h{+?S-&GW54?W9R3E^b*1>*p@D5K^ z)TA+@T&5`xCk9m5+R#E`KdL|w+;&&f4%6q}7vyGrz5e1TI|DIS=u}A0N$j}cRId9? zB0Gx9J7h?PHgZl6ErNy;BW z@9l9iil469SCX*eV6c=Q7v?Oa$YbNDR1ix$M)Db}d##p+04VJ)Bz?Vrvu+$#LS`;~ zv;z6Y*N?b&rp+@O9vzi@msk_SsTL;^Y0Is(No3AbhRMU#K=V~PFtpZGIBxVJzK!w) zd}WhfMSCM^liR4~p8%q7KXJ38z`Pzok^v(lsIF+kOtGRiG%bxqx8&cwCBAe#R$17q zOU$0a6ZQ@O$vFWr?zQV8J~6@iLyx+pW?C>?)^YlE!_M$TeXuQS@*}C;v9O7-9R&VKHa(f#{|0K z5I3qknOn8dq#fBZ6oO^)m_(o#eUf$Jr!<4swiZ^KbE`bI`NDC`Ufjg793zXr^2XKh z<@NhkxfOOqjb5={>7$wta7gP(@5t}gVnp%|jH4Bm?0X&0um@UaXq}ifczvivtPJr> z0`eEJz>1iesm;Y#Ee3mw@Url0X?ooq0ZsoMh2g2+B5uF{LFDObwAK^I`c!kvM{P}Q z{$Nm)QI0#2yCMYMeck^;U(QBYWtl&*b6v{9D-lJZIJ*Hw)))-JnLXmUAEtBZH6M3s zOXsN}cPrlabsb$@9yVK= zZj`3(Hzg$5<1Ma?B<*-B1!<`TJn`8MP@t_}m4d*V(^(?KOp%Q}pB%bm8{=n>U9{AC z=I#!m^UCkpV^tow=t96itO6(ZpcVdT%OR^=wFbE(tt9TC61 zv(g5gS?J{~u@z0>0eDF%T|ML;2!w;GRfzR5jDIR(pJb97GFwVnx~w*|MKigRpDUJ1 zY%S;4{U{n2RTx^LQ>rI!|Tei6Bgta{0bgu1k z?9Z8Z*LRtv}Ek(Oh}lQ|UG2SWKrE7nl;5lJ4rT(|kft z;9BNgX&-!9%OitCXxpgK8V7BCF|H$L1H{!trZ$$mMsKqhk;ga?PXbt zHiD|B`+(gD{=p~5D6<9_nK;2=pBuwziTUe`Jv!pf1hA2Rprzl@L<}hE9pff@w1VTU zs;$V*UWRaVr+b_RAMz05E8U{P7_&oD?>d+2^bt8H_og zGygn26fEY1AJ|k2AZO08i|H(^+C*#Ow=lrP41rDJpM2KZ4scVU#@PB{&ij9oNPald zpoYj=c8bnfMIy$RMv0)Qim~jQ^>cJbnx16tQ_E<`eD&q>G64Sl1z|xp+3qp5EJ1M& zjwQm2={ccQVUug*V!py+V_>NM819W-0Rt_k;r=+&E3vqU=xo%6i~+2yIv5kv?0H_K z`12F?@^A@mwkiEehSaOYac#u-R@jRmZqtz!06bVTKekb;n+}mYx;0{kyWB)sty#uDAZ+3Dnfv&n+-8Y(+nRNi z+`SYD!zTR$mV1B=mdLSX+yE6fEMYc3aMahNP~m<-{b_CqP2=g7fo^3SaY z_l$Og5lZk#THVriGr{+hDor!fg4D}uudi4ZlZoh|kUu>Yy)VfM`k!}$7xWJdgVpi4 zo90(z1s2K_c#$wRXv%4pqj1HVC5pRyV;>(aY`3>ZXqW~qASQjEe%tCSx)iK_SBAMN zuZ|mT5)T?PO3+}-JEqqMI_pwx`Ff|9NJQ~KC@0p-$a@uLPdj6r{D}q0U2kB6MK6Wt4Qp9`S8yOj z8CggxNONoX*}MVP#Zs2^<5=(MDjMb0V1I}1^k*O!r-N74X%<~WoJ9)IDBLxtob)wT zQ^i@1Ip$G(hx-QmWJ%_++)t|LwyxOq6lTWB$yLc)cT*_&ahJ$htZIeQ+yX&3*_C_@Yv?P4w)h#h1ZRk~91AT`$MY2PqZ7-2+@js>E~`CnVSFFc=aK5EKgYLJrZ$ zw|4OwO_4C4lca_a+~aiR-W4%q__WVUU4=&s(8@^H@RO0c0wP{kxVW^DoH)%2oAhP< z5x#(GX)6$DXXKBrc?N!rS7~hae{_)@r`9jw`BjbFu8DN5)QG|MkP#o&^oyX{oRw-uWaDV+duIq}|%>QGq8$R|`Q)grK=hn&O32L!X{{ zn^kcytmoFP(s#ul8A%MF3YlcyliK=ICFWkiE8!#~_L#`hl!zE9ZK@&dOO8|C7iR`t z(8?6jejNDl4LV;rY%GTNPDF+U2k=;Rd)^7<8dC=J51%YkfWcn4HS#D~=4(ij+3qiI z1F2zn4I?mshZ>s#4ST;XdPJ)fkqE7gB*_!z7jm2%O01O(-w3sl^%&d-KA@GVOacan z7eH$Mpnl&q(ld-&TCkTuKZwy$@Y6N=2pkv2sRkxYB3bNZFt~`jOg274Q<_K<-hN1N zv+#Co-~JDOM-~7INpEo`X!Jh*LM)N}gc6#QCJ{pxfc%-- z>~qo^sX!#ZRAz(|iR_Pp+2@UWPaFq~(Nn==h=qh0JWwM-sOUFa@A695TD4^1d8SV6 zGli+#CIx?M!;1S!eK6|rd}TN6kM@30qhXX?jw^kW+=^MAa+fM~As-bQ{YFcTaYbNE zR7F4FYY%pXsH~Di&ktSJrTYrMwQPAdTC9g1jXxtP+R4o>SBj#7kS&V!75qmCR}Zf$ z@cs%xJ7)abAxj*Z%-@!<#U})5v3JYC2-C_QRSE=D6t{AAjU5)kMDZQ&e*tn*4F3SR zU-D*z-P4OmX?}7KBkcOXv%YGRR7B#SFrvY>NkqbENyIhY zSDE)fH5H}HMo?9_1maT?n$V$DDWAPHclSD&wP?qqboi;iM7Vhm4 zmIZBnfQcm57Z_@z4Z7+a0o4BVry!za!t}t})Do<|Ec1!jXfiHVY~~Kiw2!AyoJ_TF zwC>Oz#Tv4F65ES!@w^mO1tA+ zv|&u2oTiu6sLqD_d}AH{=zrc~Z`%)WBOPUq%I|aZpQS7tH|>1TdIY75V$m7eLrWFe zm4J@~sk`6M@xvEU^ST;92SSqYt!+!9#PzxQ+Hjb|h5Q!}B+hNyF=i5tsysTA*IM@G z`#t#2-q12*z;%~UT#x?AIEsI+8pLL|MA)ZbuFXeIs)?=}CY341BI`?kY{O+Sm5K_( zCU=%sTG@0>;B|Imx0!HwNJw;&hubSl5fOiME40>FnG?b|I81ZgE$BcFZ8X9sXn!V{ zIeWjKD573&krRZL{pz7&6dhe2Ftrq#jMMU8nlLEs|4I|Cq0jpVwh1<+?&N}w$$4pU$Y+@oeGV$# zMJ5H(b?TBW!laXQpp?QJ`#KMOIil@^N8L!FFjFr)GqLIkfftu;fjM3%*NcMVutIvR z5Dk~B--=r^(9fi}Rc2nH2MEXWZ_s)g&Y|k?jpcDdz|Wh=;}aj60ysj^99sZKsI;)6 zksF25JuwPyJq|{dw$>o31NIV85qmZ30C{q_h?ZBziSf7H%v4?LdRqA2VV`jyAx4fv3nkQX^;n9b*K zz_QYFD4*lnt$l92;gwMP9HwkNj@tXDy+?!@k*=1jR!5Kka6%Nbd)dqGwO6Y`GGRSo zRmgrYf)|nRN0pjTw@LUvZ?Vs(T?<{@w`e1UyamV7Q%Xq9qquKlRA34Jv#{J5_XmL>MPHnjmF^%v0L{V;LnRP+Jsl}T6n1ST|51|+oRQUP^Ur@ zVbwE@hf(rZ9Dd7mX?1~cs^9tt?hkp|%y+Bc9-2WtZZUHc`Uf=CBx{qliaL?(MzS1n zr)Bq0yDM(y-s&3rEI2x+B!;>uNsOb_dYJXO#(iGF$G6-T-GPQFeXl65bm~G)=ym?_hX2OH|LdIxpu0`Uck&p@$9|PB0!W^}BTT4QviL0WOyVJJj6?P6`t?@z`W2 zXSCUwQD?CWk;mLb3b?N~&?c9WYA;MU>w~iQb7!=%c{{||w}*%;Bp$L52++9MLCi&8 ztTM7Mj<*7}$woYTeKuK2)Yy?Wm{0=JkM~D~$AW;>PLEe1jHC z^3K@b8^rF}M_3L5-JZbTAD{Jm0xaJd-&b2_0f5rP|DVz2_Uq4QL?76kd&`;hQ836< z@IHfYz}n|~%S-d$udFug2T?4Z_=MSb7eNqPEGg4hWLjWHEo4!@lAOMiM9HXp z$~cL5=x zbI^x-utyeA?aKiVazgNoIBJT0GTYG|wxu@6l?XX=3dws7#7_r*nu^X8J3D}X5nprX zHWD45T8V51d~xlj(k=rjO^OaxGhzwV{=T4&J~L*EMuupg6QAoN;QN5l?6j(2=C7TZ z5&$GQ%(4YxVW)g~NE`J3vL*0+dSd;dH$YcehelPR2d;5wY?TIyi|_p7{vF$ssp7XnLpGbW{0& zC*-nLH?0~8p}?*>XM7RJs|z|qebynbb9^CsjVaR`@avFGhIQ^w*Zy2hyD_+hcT`s>zA2iMQ2icz z<1M~``TgLDzZ-tfnNSx_o1^DaWCJ0^H1=Q8RMX@iX{xm&-qtCE+7F1^YdUV3rOV?g zim#osC|&%S`zQHL!_Ci$U0DAAB)>)6O8Vv`ORI*kLhQ-+dmf9;1OFM#%2%_ToPl)7UD2X%#6zadIMYluq4-ajSeS7fjMDbUAF zP|%x`o3JoD-|{|t;RX-X6?~xzC=n+rm(Re06J4GAX_zguXgZETwwA?Fd%lF|8A^K) z0w}IO{G>zBnD{3N7HMfeM!VS7b!fg418ra=O|ECm6Sk)8R!)YgdgByCp9Q*V&|{|) z)}lMunQCdlsj%+im0#_VgR{uLdXoRG?i48(HdoP6W7*3K82a{IV?`MMdU3Wh+rijn zoA-PFo1@oEI*E}!onrls<)1aZaw4b`B>U%E+hDEJuLePcxeO|Ic4KG&mZsI+gC%9f zx=)R;LvN?udxoRKUuT1($qp8Rr%^nzV-S=*z*(1{RBv(!0&5yQBcd(PaY0=MxB167 zvU87_H<02@zuG~~WrgD0LPX`7nSXCLj0n7ujWW)*kX}v5D zoL%0GN0nik%m{T(L`jU8MSqh#8J5OO56EzIoKp||!i;erRnG*NTcvw&FI7%b8Bfk` z8m?Rh*jMSU;ITgZZ|~2Kk$nT}L3*1JIqg4C*`TZvjDAsLh}XNMI3neuB#8VR)!8z3 z6$kKshUHV@rM%V4G>+QBqEv;_?oH_N@aU03E_L&T68a2t^ZGjIA4`{$_R1=&DFuL^ z*@vSE1&=L-hh~wNzKlhvPaOGp$wD9l(@~Q6v<0aLi8-5436cG*+6O?M-diOn(3>U}iQTF{!`V$I5 zJ@L;C z++zQQ_>#0Qaz&w0&2n66r71>2WT*{sK9~N)z|7G#gL`v7V zDsb2(l;O>TqL>cQHE9uRnw$fX2W&j6$VDK-U%4MbwIdPf^2`&-7R%J(TX^B7C`-M# zrzCW(vHmmo6>oNB;{V6#IoTe)dS(9Yjy^r$%>K5PeWH>5rrG;YjEIW^u!tIYP%FF- z<$zq(?Y~^rt3HW?v&J$4?(PYNEm1Hpo*kjW*Dc~R>kvR-PBi8q!ZfKUIZewXO*{z_ z4brG^TV|xQ;TEgd1^&H1DLciJKz|Zs%v(;`(;oXCVczR$0zAI%b<6nIOb>8&HG#4q+g%&~gdqTtASi zl2iw-IHl)HbRm3GVxX)n{Rt0mU1(uCWsfW&$iqKe(YBddh@jR7#y$m^-NMu!tdzvM z2^NB@K33abMWFY*!_iu)eabo!uXzPVOsvb%FD8K^-iu8La;62DU^f1;M2$AEO}=R zG5xj0i5vGtNtd_Z*=Q|>oqfdV6&~V9<<^66aP3L0s_5+PyqXnpm2&0=#k_SO8ujZ4 zJ3>EXJOQ&_;fX5CNzJC+*yAFBZo<9hI?-bDt=*p{$`bdHqi`M*gNP29LM_&*!ymqi z*{|=4)pz^^`VD(N17G)k{O2^7btoadu1NBgT)$%1ny-~z4v<#%xMYeyQYp-RU%r1a0(y_!=9_7^YVR^Ns9^1}WNTPa$sbHLzgWcPE z<(l_%G;_15k8-aRZV&6b@J6&U>$;VRTBQnUC*-%0e4%}r!DI=6n&%z68sO>-9B7zU#X)2ZeChUhG<7H+V3QMSW~ zq@YiYX!VWZ^ajj$Q_l|&{yXE%QpxN*>{MPHS55c!pLw*&H~4UVYyF{msZ)3wq1@A6 zktbKOL?@YC+rA zgEYh&BKW;%I~x$iTr_dBs&hwkfBJUkYLRaw|AHR4W1og3=W{b~2m*U62i&LtUH;^! zyo?28nFp1}mlhDeGd=G}xk}~BPR+33{c^Au=0_;g5tSf(s0g4ovYIp)(TY$ie4z~~jvW{4!G3ue)T;|ZZL-j%L`lNC+#E&^@_8xI>^vAoIN}^ zgf(4^qs?B5Rfn5Hy$z0>3ui0mS|O{4#X7fBl}3~kS>ks&6`ATtb!lUKgvx)vnXbxM zc~OCLEw)HUP#3tdoS3okVlm7|1SRwr{37n*JCyN0lo}@;%L;#*jo_q98xHt||J{3! zxAlN48ksDKk=U<7|B(o2nS38WKl~#iv(*s2BfSMf`D^5>%znKegUIcb&XGe;ox#dZfy5O6hQ;-CPv2~tjrt!W>vx6VJVPlM^qf$-r3Xtro-<}17XI0{*TNMl zyNS*y(Mm8w?Up(Gu%Gf#-Td)B1_P$Ur)?dWtxvO%7w}rpD`I(g6GbCuJSCHd5PPw9<_79@g)M8fnPPjarWQPS% zN5@gWpMCHQIyX3MG{LqeCkFixa9`B8Hw@t%QQQlRg8iugf<8Y5;-fa2ry+?3sGHDb z6iaX)MxX!}H8hAh!Quy~M3fj%p zinr$qS0WH%m}AKffg-8R4>Qg0iFzP=%|cH1yI@!cUm-tHhBa;(KtBirRx65n15Y%{ZhWbESGfo+yn5KP~q!zEy0Z8yYv zRDh-b#bxx5fTCN`0rk+%Dx-0b=J;}=JdKeFTcZhi$k8(wBlE7TFM>q?kj|t3e|z8B z+%}FZx}W(guu4uP*&9)kpIM#F-tst}ncU68yeJo)LE|Ba=V_XaL=f?nZYyh+&2Rl+XzqP{*}W$I2o?2T*(z5zamrTPq$`eiq6GaST&h z4W~-NbiEBD+(oQ)(QC01dtB>ctL3Y9hFX|X`chD@T#?>p7rnBNMOdkr!E$YRn@$!5 zp9;@trBe+X0+8{xz;dBx`56#K=lAM4KA{%4t%KWQQgQS_YKzkj)4WK~M5B&Wqi`C+ znJX?}V&7dU9u&>x!fA08l{hS!O0t9F=Qz??JWUH!+5bFOLC@*dE|02DPPQFXr3(wI z)d=d!$&2`O;oe152SH_ZgjkU310@Pn=+ApRCRIKW2}we@<`y+5@P5Sg=aRzF7sM?r zv&En&fN$~oZWm2AemZckz>;-cyrv5r7~0ApW_>DH$&S~w88EhSvXGn^V<-iq(0sQz zRheqC?x6~8k@ne_uilq0ZR7|3&%t;R;yG{#|HM;CjijOE>sP3pz2~3+88EY>t3LZ@ zczPbkpXlu+|1Dd~DxHKEQFtk+l-3)K(r_`78|Jj`@(a*9dWrY5FJI6OG+qp04O)U+ z>YpvfV=UHUK6Jl*sdX`f!I?4w@=roqg_=YCZ|vWT81@AXUOuGuW*t7PIpGgg(_g>p zKmSzx*!}Ea>}^Ur)IsETL_htjU@|TNQ~Gq_+1uH{|MvEGyZV3e=gt=V?(OXDZg21I z?{CBVt=`V|-k(@^*#?_DAXo$mV}F_eg#?rrmaF=HM;~j$k<2|FAD%o*ap45BNNkWk zgWtGVrnFuBPft=*DZ^Iz6is2{9|9iZ$%)w9&yeqs;m@0d^8kq>ZkH@vgV=A_Ivu8r z4X+iGiyaHj-gzfVigF_w$bYMH$XR+4hpD-x2c2rRk`CYDaRH(fSra-uoT4mtq z_*E>1W3uG^$+~oTV*LbkPgOv-3c5m=uW0B*<6^fSH2u^z-%`>qEKhCq^bU z?;_AFoSErHLIMI4N@T*j3%;EP+z;$L%i$v?!S)_E74pgqkV3G^I+Jk%Yps8c6vWov28t%8QTOfRp0tT<~~I z$nF8gARbMlUlnxa=)yAxQqBh4Pw42k2nq8!*r*UmLULSNOf`rXoa*JuD+^|pHER^j zB}WjNviVhq2t)*uI&5s7SF4joqjr!C&ZBuqa&iaI-KN1ziEjFn;XNfFI)zb(#7kSg z;bb8}5FQrM6Fz>br~^ZCwh*&`C^9icX?EO_jsx5dDlCMH z(@8W>b&sVy;6q}Kq$iu9+onT%^?VAYCgJ!na2>sFcmXnjHtreZ}i&6l(g23wF4Km-vl(h~K1l_zIrk6<*;L6I$jC zzM?01$uv3|tFkqe*chDt-(1&%v>1*e=rkers^LQ|y8W2@9Mc5QDMI@1R(r6PsC3Kp z_&4SJU8_^|y%AUP=&p8{DRH~LahK~VEpdgbb+w!IiVEXG*XlyI>QZ%aiF<8**V>99 zxm;?S_LDo`R8k{(PI*~$cdN9kT-93Hh){rY0y}q)xr%K4lE%}rAnZni|0kuR5%(13 z%5_e|mRn+_h!)4SWm)+faoR(lc{DAfX;v!yoE2aXr`aJ<`i`1%kbr>f`fM>3E`2GH zb56?fQhcg8Ta6+R8jH3{NvOGw>Z znK~)u>)HA%E&UaDv3RUqJi?#{YPr?4rp>h4Tz-?r^7{9S%51h(cWp{<+O)G(QbM&0 zTQ7_Iis?4vMKz^-%gZ&T!;55Go6=kvt==(mW5W9Vn6Ng_ z3QvjsZy3(T@fGS_SF-+9+W)q@-EG_cx3$&X*#Fk?5=-!rv7 z3?pA-LgLwkLoPu_O;u1;)h$*un8H?h$(CtA&ffh7OYA(g~ zp_Efe(V}>HNY~D&W&+e5@&03keCX;$G>PU`m3#qSRi-Q89fV`h;QWP#rz%Xz>MtA^ z+v6?BIT9^cO57YiXYtTs9(5qI1ffr|YL=PPTm{RmgeN*va`m4h!(?66Jpjv3Z$PWNW)i$CnOI$Ev4_KG zFsCb?=6j#D2J-j)M>Xdq_u@QG=dZ%~Wt@C6@Tk4d3JXU!LtWI)$gzKT9wa_2oDV2 zQTX*pV1?5utr*M*OcQ!tYcBzZNpO&iQfsXQ@T#95gku0^y*6vN`I>C=GHqgIfb6H* z8Lo8dwPq}g+SJY;M*O&v0xdYe1_XeGFs*8pW}ew}E_s@6ZJxaUhl3ZEuJ<4`<1 zX@i!HMLLa#;TxHp@i%o%Nq!!UJjnHS=hm%Dq437imcpuZKcnWD5jGp z3OnXWI`_%gz9kha+l+_k%6NpE#VllPC!=6aVP`e9F|BMKd`j#;M4s{XN_2(}$;%so z%I!b!$KIZ0|Jmy8ZR|g5d9t&J!IfW=Wt_-syWRFm)m~gVr}SQQ=*a2dHYDeEJ|+7f z_{lIzlLdKnoGyl=a7jaO#s2SYZQJ(W?cUC2|F7lA3mebWoPWpXT=Q7bjlnZIj%4QG z<9yZC?85EY@YMU(wqa?mtAVFUG(Av}<*0rAjVTV+s%}Vzbvh7y{%IOmT`=BNcftX} z=*CT3mN!gdy-x}KPfmluik?6Gsqp{V-Rtd`^uM>izt`K)|8+bTS)n->@mJaw!KZH+ zTLn(Czw$_e_SG;X{|oaqJCNLJKUYO@bg&&e?-3mZd#=n)L+^#jc*QsW!QIo zv%$NH6t~iBIt$vWfu-F1o9}GE`X?J&@yg*>qcb37Yo|Q)MA0$|21zhLOD)}t(AEjO z*Xg76`7HRPP2#8k$S9hhFHW7GWIDm@4TYr|UI8hJ1~y`4Sc~i1X~pD&+`0np)|K@j zi|T*#ec*vACc$hi<6VJ-@!k@PEn2ce5H#wp;F@#7L#w%ZoOPuMc#2o=#DF!l($23+ zx=ULwKq~69eve`eUIn@H0u9Z5;e-UE5eDCzhwXVx|0+1Ma|G{_e!lm`6*S5Z^;EI3GMG|T{fkV2ANxV z_$KXgk`GCgz6nutS#U&4r+hicYu(bDr{TiVnZjxd%j%Z3Jj|~=9;KubhB*F>jU_cS zQB_*N+vA8?V*eHMvAPMk%KvA#XZ!zkce|VT?`wH1>LG8m$hj}@{ZX_*5W*GdLUsY> z)&+vF5t55dzj`MZ6y!@7yd8f+0XJvXZE$_0la|1~-}wKm<#F$Q8K9%U6UZk2QVwp&1xn=MZ_NjsQ85hE zkej@D!ML3AJBV%>{A*-1Wdy2v|4-s+grU)IYXA4P(Am$v|FN~T+5hW!G;QKT<{t*L z;1qZ`#uN3kgchm)BZg`gD*+E@gE$Fey!JlnU^2i*_9}iU7LAl2t0>6tM1b6gbk{7> z-KgMZ>q3ebxVc!x;x^XoH7p+YoXMS(h5OE!PX5k$Ri)opf#iCfyRM)!Sw#Bmp6|or z#`F#PNVmbrO?LA^?o=1vT1QRBqdpekLx6)g^zkaSuyv)6)V7Xli9j5UDbgk-*mE4qx?#w zv0GJcIHhU5L3Sq^TQl3Uo87R%CE1`{D{Ezka`tX1TU6cq{jkTXU3w?jWUWoVVV4_r zS<+}Z=fnh4hsw~m9tKKzS+%%!Yi6Vc&2Jd$k_^>aLZxBZuA8k|b9r0YtKH4t51XyK zm+uC#^Np3qXnf|AJ?Pgw~~OzN87D!v43rW8eSZ+S=XS#D7`K(@2eh z7aUUjnS`T=auvD!#eP=nMkFyh)N_bCBscArLR&1l&})>7UQb1o+h>^7IG)bxSv3MQf^j5ng1?LpASMA8lA)6R04ois$q z%M5)_dT_VoWck_*7Tw}-df&k)-#K0H-V+A0wFgDtwJv(6uy%UlV?0ygDG|!y$04=1)tx(+{!x`8--y4y~1((pOKv zC6Z{#8L@+wr|l?i3;eaUq2s!fo7&1IMhHhN>S)K5yhmqe;;wsduKtvq|D@(02}5)iVOIMaiT}B^y<^A!+}hvU z-kkr|@sx2Jeg<5X3E}UO3rIHG$*vt`%kFy2@D%%~Cb}=1g%7?fB`%0Bs~`x(E}MBVM1Is+m?*Yg}L{1TqvtGOs89;yknD z%6t6=l5iSceixppY+u@o%4Rt3mS1^)aJF9isloqO&I4WL|K026;{WgM?r-@2I-X|w z-y6yQd<*$=A(2~uUTE3!68WLCsyCA-x|U1Xa`~bqg5(TAR%`f7smAW$C6(HBl)J)3RjKOChlok?TX| zEzdP=kcj3vr;X}`xu@+k&TYraz?7ZnTJqEZ-JK5<&XkmS`RTfjYI@_OuNX#&tGoE^ zS(M~^45H)UQ(L;i6jeRMQqL`anG8r_5>?xuyfm5Wc^Hi6=f83&PGKP!!mdu!<0L)} z(S(qMl-SqRqE)zl`c}nBmrUcT*Dp@zS|Hqx;hzBTFf7KkDpERW6@UtNe0lO;2|c`< zNq`&X(5=0A3HB1Xbn7+0YTEr$HA2{lWcX3GP5v=NQ}vhDDo-f+2J?HMx3E!U0I2X@(gEU4ifFunhla2k7-Kk zatPl4VEB4E1}2MfuBvHRSe_%fM4One*#IwAQr}`!aE5B4ZB?CKU4&@3sE3E8vkyyH zw=)Z|?A`6jMl5@D3$qeuUAwc{i4`wfHcN300JWToH_x4UYUux0&I4K%|8Hl^nQ#gik$obcJ~!Zxpai0n4n7CF4ZpJ5v+|+qRFC2-d4h(RV*E_8;V_&;OT? z174;7>F#Y={C|75x8eV5d7A5g))^waj?>reksV5;{F@COUgXO5?T!_j=Z-u%`hRkC z@a*N0KN((M8|CzWXJ>2AI{)={cXl`W|Ft~#*pXNPLQRu;-rr__|64Q}u{0SxZK2Cb z+V6Cd;L_)bQ5QgF$mJ2Ke>~~rmQe1+B#5S+AWi9G8ly)T{DX3;KbwwPK+J~o^QWy| zxBIyTRBAkbnxnw2zyGZ>`@848>vZ1t***49ty3m4$buk!dc{WZ92kJlp1o$TUcY5W z&z`^aA9>!N-@TKVemo7*a}U<;1TPrGEEo=Rr(7mGN{*z?OuQUIG==Rl z9_Im6E&}Wc_3JqYfzEpK^N^9Fs`oZlpz$SjgY!826O-`;X-KS|eY7Ee?3<%py^r_U zA&`Z5!cL@Dk@ww|wEjOfdI;?lws&~)EXC4M$_BxdorX*Wb{q1+eH3-Er3`_uX&MhA+IecK zI9?D2PhOnr6UfKLg%;2Ijr}7;pA_6_@SkVGxdMNsgCruu5c|#ht&I==SN_NNMSlS_ z&CMmIl#TG?97JcRxVStI0YeE3n0C)TTPTS(pR|Gq;?Q@s=DwVi@2UQE&ItniC%ew& zf}J^|)*HEU5&VszM<*73_rA2S<&xH@R=o;R{rDOtK8c1nFX`To}ayn=f_Ey!c10xKz@*7@Ied2 z=zKtT@hb^t1^jt1YBD7KqEemt1Tn%~jV*E|Z}nTqOIwdyx@S1Nh0zYqTVJ*Phi;@V z0LpQY1QXf}IA`)akRo;_gMulqlC3NkGKH;hV zDqb*<<^Xm~G$@Ni3#f>Z^aI;EPT~oYs0HDNN980mi6-mx#*L?!0)QMMmCD+1z+GbZ zTCSOOXqR>Aur2{Tj)w)%Y)1!c)rz@l^=XP8w{+i(R=-D0BJj)$i*YwB)+WJkf;a4k z;T)2ck?hFq?l575YAvLBS9L+!7%MW2h&alJM9#VLIv-wi9_oOm19Xt zZs-J%^FhqdHzGxrV*@NmBBGNyQljGq{1~%NlN^ITL{8$&%bca>@nSrz;>ZP;Y4RgE z5MOXQRV7sJpE~z}>t2Aqy?Vr$j6!^OA$(jFW_OSV`$s{z` zJW6!x+#7(TJ8ds!ZSMT`$Tc485}^-bc6@o9L>JLG9EC^eAQTuBE4PMxOI1?M~h59GJh z1sxjw6ixwabS}*9|Kc{o;xjh`bQ=unor&xo)FZnk`u03>kMJuKpI652)Xk~za7~{C zs`8jcLCj~*<K}r6E5<3tUAh-3odP2q7Twcc%1Oq*6y9&o{~l;_R?__o7%oBeq7;i1byy@{ z2mrQX*)M2_eI-SQqJT|fV_$e9%5w*JDwl@6rIS)IbwDS zHWZ#(lMrbQ0b`lWW*n3QlA-1Cm7hul-SK5_%GFv_;4ou#PMTM)?4qx)33yrkYW-KW z!mF-^%f9wkFnCc61s*^sNt9PUEaPc<9-Vu>YoSs9`wxr73;jq_Iy?U*I%+Fq@69kaT7-pi@+Iz;OY1 zCLEDrjL2-xfxIhl#9pCa+;NH_=R`}4kF)?-G(a6+23INBj%?sQ9?C_EWA+Mq9}l?- z7o~Ty9?6~Ux&vB{_DV)wdHv8?tFAh;T9sL)yF{T!enq(_7?H;5GEf2!76Gy!p#CB{ zI}3?h6IfXh&@NRWk6|>QuwaTE!}BqUNQ=`5)&sW>;VJHiX#V5kG&32+NE48%bFk0} z{wItm6|E#NjkbM9YlT;YMFJfblevrr_S#jhWjaDT_Q4$OVtDT=G@nUqY$$Y$Vn7ARxA7j2TiWtM=yuFP$1CSEj zy#flOtwtI%ShyjbUZ6YE0Vg&<$rcGN60SodeP=ukRUurqxn?*Y&&!DGP)FC-KVQ4T z`5SAPuT7;~hd(M;vC4uq$oY!uq*&M&bqe6ribG-|%Z4rO`s@g26y+E0YA~8|Iu%Y_Jt;awHRu3O z%~G@3(&JT)MrU}?syWj2=~Reh>#m9jVa7 zSE|tOyw02wV+>V7496ZVQn{cw8Bal0Po$z}h)PRRQ6}+4ga<|~?W1bzmh}KvX*5AhM|0@4I8m5ek_)>9WP)?Z zm8}XZnh_e>4OTN0EMpmHY6`eE-M{m`k||Kr79%CDEJ26Vj5?%?845FiPh1E@QxjZK zu&^)BqX8)pue9>w@QE}?-Sa|y$YnSl`|ObWqdh;q*g<$5pv>@l&v$kA%5}zRiB3~b zq8ab@m5BI&jmmQ}aNh+A&+}mLiG+)HhmJ3qt7I7^5gkk0;uH#<>0~fE_vH6S`Y>+9 z#Ikmq${LI)H)=Jx{brKtq{Y>?3xxpGOj2NTit_=!g=f)cxvgP~Q`5zRj+`C=+g+}`Q2qkh!K|d~`NX_7 z?c|3(nJrgP9=<9`WrxiKFx7zQQ=X0jz=SC!lwZ20TX9p=8$IxvMZE#nd2Nz)uHak3EvY$*4WZ{@kht0s~9dMP! z41p!Gy$2~m5Pd-XAe{tGugn3!4$KZj_Rvg021Xdk{uJRhm($6~fP}^)FvSD9e_>M~ygirbRChQ)Ff1_>?} zp?R;E13kBsuH+kG{>oOrWi{G*+`@ad@ZmXCguf}mM!z+=YI9gz#r!?Dc^Jz=h=16* zZ1Nt94M2iD0k}T&@IDe|N|B(aj>>bxALC2D=LJ8a?ap02VEa;^hx$tWpa1%A^z@iT ziMeB?AWW?(qH*JE;uU7RqSKu|%uFaB(X1p~H(nBJ90b}ysFOub%sAbr`8*5gd>9Nb z0$wzj+rv~$p?FzVDf)44OtkW&D({ZeW?;LgiwG@GQ|S?bR6GUhfv4A4NazNnheEi4 z*3)nnpd>%OdPK5`L9%JixwcQur9_G`r*G9VXTum6CY~as0A;j{QZ}%F$JMLA#9Nbd zne1VSKS+7rp(Xu7@&V>6-NG*Y&j^x%8=)NY_jqKCzpd*OZQhn=koxoK~S(&S1C9TQY zTpD_58LP936yJb&)G;m>BuZ;)WG;!y%I<)%IiFsw8eI*I&qgFL&0esz+m%#^PrEIT z@y&$DHo&ZEgI4)4)?yc}$PU!}LQ`3WlcjDlWdO?!r};c06-(vL8&Zp7jn<_S(#CHB zTg}*51gN3Wu?S4f-MpF+vJgrQV`ORF5~E~My`_zlHG)U2Y%VKmZL@aZlp{9)?t%=H&5;`#v=fAuCon_@xHrT82=p}jQ_Q_4X?NN z_9_0?&hDSs?saye==p=k|0Aty^BE9fLo+e$U_WhFLVOK09DPW;b-LpmRK&t83wSb36E+cVV^i zt?}?jeH!h5aS^#G0jSvjJG;GH{O7&>oz4DV$8%4`-Q$x>o7x#E&%4L1XYl`k{p;Z6 zi#Cr}iKhWNa(W1BFh=j|iy(>c{7q*X)YxF~Pjt0`KgqE|MH%-!PuJM=SZ8yLK3c;w)S}pt~14s*vgO$}nZVWwJIxWw(@f8;I z%u{%umex`l1gOb>snv6@zKX>P?9IM>rTR4w|5WyR6#y!9ZPOopPR`olXY%Rv$MGN-d)XE;Qag*x;-0z7cqHZLSRJ*_)O%@v6a*3X8cjso zpfyI*NN&VzW!=0dn|Afm%aVM{b?{I0#aoaMhzbWmOBt;dGKV4h@;ZSlQ_1NVIB;DIYC2IGx3)eusrZ z(8p*ifn7WN1urg9ECpy_8sdGkAh~+XvJk)0cM9-#ngoQKGxR-rkfHj4FMv*>Y>o!A z1?`K8_^k$;udE%j zU($GroqXE*;v<(Q2Z;1t_dPlPU?;w|q~x9&sgj&$bTh%?Bded!kF8!}8|hMgrBfkx z6L!yhkxEC9klu+uzP6|XAV<+m!W7*X-RR#}cq^EK7jZEBE*PU=m6S~bJV=T_9L01P zSHRmp;WdS`@De44g^c}!%UcJ@o*xU%go-ZY>*vXTf&7Ij8!m%6zgf%pIPol{ZHotu zr#!tFu=ZusiF}Yv&qATzu2h{FSYHZiz*Uvt@I(T_x;SQb3YHouuYXP0~ z&4U+Kd|HXu45yFtAY{a$r*_kbvclabv#Akmfmc4#!`H9g9z1__bmF2;=p9jOxc4Q( zoU|%)yTHCE%B5a&@}(xb^>dU)b2;a|t$n`>|LgV9i&A;)<& z5&c^Cv5o$H6DgadW`9~*{`&y3&@b+%lf=fF(|Y;T)>Mw2&-GrVfv zYPT#|&7-cWn~1UnP{M)OEROfnc-gRXvm~0% z&sgg}()NE~f=&b0{b^l@?jwR@1!_}^dq>!_aa!f&;LLVJm)Yx1F;&Ut*B+OSa{gPG zr5Fzyg?zB}zgn#Iq1AkIQS5FJ*P&*2Wkyu&FGh0o({s*4`qh%A7^=@ZQ&BjdZd%&` z91{o1M#nSP+d`IdIzaIuSLHXLBJn)5Fq4PEF8~hPry}>cTxlWzgA=pr8b>4C+Cy$T z`;$+jTOocrU`X+^pOdW0_JGYW+$N^lgUzS-br3nXC$GhJ9@akLJSqY_)yJ;U8QDZj z{K%a;oB(cZ7TqP~zwFXM4R4T2|BszrTmIYK>uuz}bv(NN7m$UtqY`&#mxe2ncGplM zl;zqk8##$^% z9?xN#J_gSIWmA_Ac<<1yxjQk<%zriwdb7??$cx2|5#Y6QtB=bqDU13$-Z zh8Ac8m!)Gb7{496KO1~+%Y@9GxKL$ijYPX1{`G4=_nBYvwoVv^VArx+Io4dga`3d9 z>@G~##Innks{lnAqzf|^g2Gfc-xHV^;~go}>}lo82lZ!`?~|c%GjL$5P|bR?B%a5E zc-&`i506(`g=37MB`;{2{l@SeAPG0}Jzmfmf@fi0%r06d+8MjgH z=dPCy4wu>bG~U@3)Vz`-a-XncoAetT*E~zCCRFd-79GH9`(NHoE++$(`+wWM|FOT* z-P`Q{bv(7SYh3SGOejS0W#~o8+3cDqheOgR33WgfatHAOfkT6Tdo_IJ&yxEeL-^MA z0&VX9xwE&kx&OPCXQlbaf7@{Qobnu7MQoso{_pKr^nbg%x4Y5*uH|u(_2YQxpyjQG z!e85390qy6tAj(KLLCT f42Q+8;fuD z{~Dfq>=>``Cj642$hviT9!@D(F9nC21%pqRyj9%*7V&*Cidi@wQyNm0+WIl2VVGmq zD{{Wh-oriu0Ml?JqH^<`5;6qqpC9=Qujx^E^%?IH=5nOVOupwod-H*^n*j*nrSS9N z8#auR)bmHtyhH!;?tA{}uStjgl`qam9sEcBnO;mg8K6@b-(p60m{adBetJ2Be@}x? z@b7$rzhi*o{pJ5bjh}-A?}xGH&yJwoSrTJ3C(n14zjaG$g88H}SS-(-;x<3$G$R1mI-(u+p9$9zww?55et;8~fLg44Xi$oDiF!)J}>Gr9~I{ zrGFarG6|qPEvK}&jPDJSp}0lNff|Vx2@rN)TmxY;8>t~i!RYA!|34k3Wof(Nbn88PC1;20xx@dX1)W_P4<`bR;!y)&O z#tF{mF*ASq-hiYm;dMjzs7<6?dm3+mzjPvRPfI>-(#WD@qtsiF9dUU`VHaxXD@EM@ z7k4ayn5GyJu*c0MPzB=T=9`wzG=qhL*-Pu+A1DKGE3`1>Qy&0r>o;M!dT+F5K zA#AM9!U?RTABvJ15q34JLQ(>GfXXk!iAPvqR%L^gdUuR zL%*$=S)qewT3KCAx+O_)vp!;UA&T_jiuB}Onl-{jdyZ&N$X!>Bc#V>RgkgcM9j@Cc zZ4itGp{ntmk%hh1fqc85RKBN2rNXQUC9~K#NrFA4o^n-{N#D7gR=8?bPa9A0%}(6Y zCQge-WQOMx^Qcx7$pMt^i7)+o;($IAG8ASTOhyYH*a#|OY(E!(1JaR`yr*?TdQ52* zVdaV{A{&(6F0ZBC(&G`-sUj!!nQ)cKpB&t4UNjF*>%>GZJ37i)L(r31<)LVM(A*B$ zfDSXe1Fv4Z88vr%XRljbGov5$wJRjlv?NWbumYGPYGwDmF)d^K{CQnvTlZa&esq zf#voRGk_px?nOzzyj;dGO>45wglnE7M_f_JMwJi7XE5e8b7)Ohq;2#h$Dmw~xW=wu zcaS4Md41EW8mC+n*Qj-J>7AC*JQc;mZmfNB>7N>Fpl(J7rD>rYJ{N*aiPY=15VcaK zbph-8@~sPit7TmmK$gtC?ve$~m94r=3r28k9ZobwB~g12w9i2B)E1yvUILzC0ytbW z;QH(!1?~wL3{oOj=Yb5Tt&ipK01mXj&;$!eqPvf|PJ(96L@q40#f(S76Rkc-5sp~y zXx2pQm;iTrWe%wtX^O+bm?OP!fFjvfLyM$#G=ekSc2qPjU1m`#2;`1r1(dT-om2Ho zJGn^V&yEIGMxoD9G0~OpMVQY+ttXOAQ!pmkiN^xLWFEnFoHXbb9QV;LV-R+NS=6Ri z_w0ffJ^wkuMOrPu@`g^rv+NSjWboic=`; zY#%n_I64bauzMt_-=V%uuNw;*a19mr*lSq9S7DIgya9*Oy{}U$>8#5>w?p@ z)Y);hjj6cFt3nLr%?+w=+zOofDx7@J>#K1b%guAgkdP3I5}8Y;N!ebE6HP_Ja#Ib} z^Tc9Z&RQpAU1hJ!KsB=22{4(}&hAo?;(Oc8b;Woj!GKe`0aRo7Zs*Q0jbDU|A%S>{vzEqgy3Jh~@ z(_Dc8jTdiVwR79;N-TGt9+^d+3vEN4grFJga0~$a@JKyQuh{N zPOG?4{?%0e-Mnf{S8H9fs%oQg+Gw0^P~&tRvbJf(G3cVxlH=51Z)En3%wAV!|JEWq zRlHpi`&|*)H!}A|=3ZLnwq%lz!)eMzvX7ZdDEFe2A5^B+@1rE0J0ZO06x{)WyTlvL zmsetclARX7NdBf(#MK60XeZs_8=F8}}l literal 0 HcmV?d00001 diff --git a/golang-external-secrets/charts/external-secrets-0.9.20.tgz b/golang-external-secrets/charts/external-secrets-0.9.20.tgz deleted file mode 100644 index f73d3475933bb28ccb46503d3ab2ed4875bb8bc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81759 zcmV(?K-a$?iwFP!000001MEF(bK^FW^I5+Fr(`R3)}$p_wkN9d-a4MSi7S(d%bsNG z>gs9(k&uL#A{jp9(MfJNc) zi`|z2l=IV5{QvO$bddeOE-!}Tv+?QZ^mK4OdNCM|ho@&R$mtW{QYvv6(SVQ_OKvTg z!)n`Ys{fM~R^W z{-5)o`ut}Wgxqr{WHsth-%o!I%x}!mpl36mxi)hx&caF0AeQIaJQ7W&JbIu3)ES|D z4RX2jlfcaj?BQID_h-dN1@$r0N1t#~7OEPJpOoq^BmBDRj zjsdmM3b-$kd9At;*^MlzOXqCK+=$G)fP5cMp_)Z3>@7URYY|0$h{N(|5l>CaTb4&I zKIm}^htgdG`e4fLG0Y39A{eb5q~j&!?lBERQ5kxMVha4vfK9Jsc~7f1wuPG5GCF$USo$?k+95^45Q!<1<7( z;hU_u@5x`Kfupq#k3nD@Zc*ewFX4_7oX;)W`?9&z=zqtv?sqoE2K_%c0b^g%|AW2$ ze~waA?oY3>`J9E(goFz^Iz5}r&Ia}=8(U}89-oY6);XKm(}7LxlaurFF`ZHR@+BLL zruNGbn|@=Tjz;5?^U=%E%h@^nn6loSfmWjtvnQlK8jQxq;LI2e-VXg>{Z95gB5N-u58QEx%K!mr4PG*d zeL{(BatAhu^}wmWa)5s<$UFrj6?$<1*d3tP&puE-3RM!M*eoOfadi-9FNE6 z`Sm{cSr#nj<54vGRcqhbPP?;lLU7VRS(0Vji+&7!bXCm}AlG$J6U4KN%V7Bj3} zhc9^~RZq0wAvpl`fh2kL?hf0c5(#}~fzG&|fyQwd4HfM$2mm|nP*P7mFoE->n8f6wJ!exK6LLr(=B=ca?5pw2 zJ?w~_A8t=5&#KQ+b~Bql(>Q^SeoHNZgYht=dR_% zcEc1+i9|!g5Ex^DL-AG(WM?O+fIFpOqbt5S9(#A-(@H= za%vmXwFIOk=8gp`p32Ju_%Vs>S%R7pbv4t-`!Bk5(rHx6S3SXv2R2=J-u;skJ{f4w zfJ(X;O9soy%CCUO6SQKw68?nrRmc9bOwVFLWT1fxJjY?d)5}?Lz`eXR(x?gy0 zliciL4uvtcn@j4I6*q06TC&u#ych!(9=d0(WKDFul>Oe-Z8q}FOiN->*!msRQzYHV zn1^*h-RzVzuB!&$SAXkdl9rccE7D@O ztGZsTDO@xKEx~sucn5g3TT{S&i8MrV^Cj4FMdTx;n=oJj6q4aqN@fmSd2!HYgC?Nm z$t)h33Whey>CSDUH*d0CnlvN_>QO}J;F=`S1mQoWUdv%|gc3FLgKaa?2EyKAZZyDX z4VZo3VJO@I1FEtWbID5Z4`@!KG|r*pr)_8(2=J1)gedZ2g!wuo{SbT-cMg*i!w}I# zHi~>lKQ+aflMfM55E3F~+a9RKzbjAWu+*(Y0V6|#C=OiQS~Gzi2-uH4bMF>>77-rG z@Hi00!f+YR9E0b*pF*JiL`qDpDd1rO32h{f*+L$(ow8DSMSVKu4v#pjsmq&d#pBTY zjv_Ug6$d<8n;!HIvA6J^hbas(L!&^0DtfpggCX>qgn6ZiIi(l}Q7HpI@K)T$^hv&z zW^^r8q)^=Dd-chI&8;Y%NAf(ifO%y4mTvLoVN251jI8PKCAFy!T-GB@E=XzAEJG9m z8o{~aO{q9xi7oQ_ShENIQ^Wi}er50S3Bu29?H< zhd|q|2sP&6VKP;m?D5y+mMy(ib{(qyn~q=$R_pd<#$6C^$)nQa{w#bGc(LCn{UCNP z!=FObP4aJ5VdUTf(OoYp2?6|m%iZ|HkK$ZjnCa9FojjQ0;CfY-f7h*F{JVN2bz-rf zXvk9E&z+`uveJrjx-VX(;^9%gBk1J_a@J8w$z+mCi^ zEIn9wVf2ng4_R!u84TXqKk z@*b+KLB$!|5-zwr1mi9=KQ%kc%EGJdtD1;2w;MXvDzHqRK;+vT=j!%VSjJc?aKi`9 z#9;NWl(Q35&h@QE?>J+S-hJ0F!6RD>WxTncwB zzI9zP*w-}KdM@>A$Oq*q_Bjp>Lw#OGb}UsjDf$LD)mh@t9lhPYbcp}^o^A6mh($hT z8ryT$G7+%p{*Tk~s1W}@8;#HR@&D&2t>gdo5vo^-P<$(eLd8BFpEB^pemqSY+>{5| zZT7(M?dcybgPuw-1j;*z9l3oo2uxHQpHTxCqz_LJvMbN0$(i;= zWns$Tp}UYOka~zZ6fO6Z1OkKrj0q?ntWe$c>#v>fupCtys-Ca>;Br z5haw*L{7`|0-L*S_%B{u*oaqw1l710hOvdF_!b_36#gj`2B3S(W(ZT$zG1e|s;m}w zF}E%D)X#??aK@kT#Q7(K^kzti!+A}Q(aPX)?5JC)72zA5kC_1N71PrBsJ zI(srA|17sfZ|c?*EGYEjIt7ycZW@M*REHu!I{i__xJk0o*qH4rvLT!9D<>o)ys$Nr z+0JY-vY4LC2OxGAZ5VGEZRoE5)mwZW%)lo7KN=SG|LJhQ|9_sct^Timx$^OmfTH@> zeqJ{#(8VkLV+DORsOD3MIhu>qZ~k;|vtg*v$sLBHomq%_Xqi?|(fX zqW{0Y|Mlt1CjL_^pyK+^2v55|?z<4p_J4FTJ}bWeH99}vzyI|trTIu?{yna8&^i-z z6JhFG6$*TngsF3eyV6qRO%EO`Em@d)lTu~RawqZg=T$vd-ItW?Q(HJGjcurHU%S5w z_q^i$Az}8Hs;Ri)1)CZcHD-agEZ_5@uj4y@?5XMkAu`_k99A!0H#3d7V@qsuSF@j* zgMvp>alrN%UwHOhApL~o0;19-%PWh}RClv`LG@`}y(^u|VCRO`%2SiL;l-YFFW~7B zIioOoCS-Vdb$cl)-X|3p6aT)V@+~}*SD`z8+Pg0m~NggP~^u3l~J9D71vQGF4JC2k}6D#Q+CXw=Zy14?J2Q z=7)ZdceyH@1rKaudk?O>=9Oi>Z$RXkdU;=piGpg1_IYsEE&vM^D7*|qUaer)%t(@4 zPRQ)_a-i-Q161%1vWm~r2(F+hKAt+>RDL-I8y{a@zA}EijH89Qv@_uR0PqPSUOai5 zQRlhm&B7uCCb>^T%~4+bp=1_sxe)RvZ~Os5040HWzyo!SHY#J{iPVBw0)8jHFA?Ip ziXEFsEgb<2%bUCWV*)+Yd=mZ%$c?K$_#=+KAECZ4!Cule0K#!e>}DX!yIab*BsYNP z7@^G_Uj7#2(a~d}{rEISb#-i`upEbcZqUG5aJ&pfFwEzMn2alo0`TaIBv)1#SO(_g zl`pv}p}{&b3l$qmBUJ$9WK*8tBP8SP>$~^qb?Jg{l0|9L3JPg%A!UJ3;w}{Ei3UwT z)#+7v8?3|8PKWVy$s-ht-+<~7GO`T#O4xm&PDCouE;oS%cLi$Exk7{a+`JQ4zZ=Mq z*4!(;g`DpoiJhy;zFpgv-Fanx2N04qs_vxM-$)TGk@~Yjp<`j@+|<1=?}*cvmuQ1X zJuJWnCP8WvQ16%75VGozYqip1UwA7FH?W5S*gBPl1raSjZSI3b-I{W(Y(;gW0{wr; z_dyDT%4(`AlGGJxC~TN$TP9jNjIn6bc3sj7wMbvjUI?q0lD(3c!_GLC45BDme#FkV~yvD~v-O;J0A4NTPqXNvFS zsp$d!f%xJI{*X*a%=K3x`2{V@FY?Z(%(67e9e&(EUnUwRKACKYW_!w7p`-kBW*>JYu0s7y{*Y- znRnkyHM#E(A%6RNaLGO=BC3Qt6fYa_PF- zFBRZ~I5NQZ3k>)RELX~x!pK!$=Uo*^D3Jef9TYJ-W& zu7xd3RqM&MHc?##_K#+owlzyFDZ1H+V3FCQ?abANCXLn1UGczk@ovla*sh|#BJ70R z#8Zb`SB@7~MU>iz#q0cN1r?@42LL~dR}!ZVRUi|!O(l5Cb6uFExH;doD^QV-7hR7Cbwd0&DkI=2H$`3No`Kg7 z!WxM((bwb=6^$~~3C+3p#oOWOs1msh%Z|uTcW*FeE4ryiR}1b^_4gYVEU8<^UgpNj zYEd>e2nMz&4PDbN#iyo0Gm?!uIwl5;>`1=AQAE# zx2E8t_#S)LNyvQkBWIvKj3}(TNQ7!fA)9G9k_cm7_!yJKx>D?%Gl|#g)u1jPOYYP! z=2ub6ie#}EOS)A>DC___JI!oy(uevgiiw|4G7|4TQsoKRas2! zCLEJ&s&O6CQ6|f^k@pMMK*kueoHy4$z`qlC^V?!Y)X;bD(fg_R>}n+?gGUsVQ4_T z-sTztX2s*0rCVb(D;}et3?q`vjdK{67k6!DpT*OPTedLZALFYN*34(D%e+~xiM!@=nMy!igdcs$y_|Mx5< zcWH6?5a?n0w0z^|Yb6vi@L6&3|Ng+}{=jJCfze9s((172qfUqx#u3kRuhHivTGXc} zMJwBs4vbb$N!rtjbEEnwSbA8r5FB;Q1B$$=?2Pvy~+m;RntfYir5^_AG&pbLiwm#ZW} z_}~9=@OKmYU0n2U@k-YI;s2;s6(d7^^Kkks?i6&>wnuR*#YlfiP4-Q8P}RbOr!liG z?EbiCQufC^_s2c|FCF)+R2I1-p7Q&Pq1g4Jf)f#>%5FspHszf1cHxJbd6m$`sHG-C za;89mB3gUNg9Fl&tO~bn%7s;alBdulV+uDX)^>4PvG{$T&x=oUa6ZS|cQrYs#ynCp zPm`ocHYuXJ)_YnVh){N0T1^3$TVh-D7;G<=bql0~$tzqO+2yMf3?9Ch5mXKEfJrQ!A%NQ-^gHSAO@}(cSEW&hgO~*TOmmfgu91`ng0&I|8`i7b$w2(T|PWu zOD|#@&I)u*E#7LNg#?ZqOi8?$k0Q?oc=FWz|FZY5%WWK4qA=RO{S*~&Oh}F(0LfOn z`zX$wy=hW*vnAOKl9G1E#DtjuiexnlRoGPkDZ0mx^}WFNWM{3Fm&z*CWhGD`p>}4( zOv^-8URGwV`$c{BT(MANwZVt+X!H%va1}16H|;h;zROr4ww`MhUdI=fJ?>ckgYkg{ z)ep)MS=E*m))E4}hRzY2jX~u$WUrBoL`gJFXWjm14)*$4D66Dw0NtN~eclqZdiGra z_7J!vR>vQJCHwxBL)Q;y?^wNA0CG4hmh)r@;BUhREsh~BBPSo_5~;D*0mhEZFjke} zeZpU>W}Q@qrCr`Cm7xiVA)y`;62x^rmW+(#?-v?bD>8ooC^63?OtGA*;=X8){t*W_ zphb-I(<^5V~cMN zP%oLU7MO*qHRQ&5Pj~gIfsMDM(S7ZXcC`(jI}F|lc*?DPn0}t}CA{rIDsC*txgNB{ zaUt>nyd(Js#eyjXs*KU;;yg%YgU}zzz~`tmE^%)~cn)s)Tv`6!f6FKs!5ttciAWS(iGA8K-9D7Rx&9HFLtCIu{eAKJk#LZ=7x(2-=6q=NtYZ21$iF|Ooq=o-`xWhBJNI*S4o;sK zYX+zAf_inNtC?=Sc0h5fu1MpXvKQ@^Wzp9`xaXMw{)1J>HhFs&Ub zXNEs`bC3c)!ynN}fujR$c__zf9ONH#e7k)60y#DFj3ql~2_PJWXi&<9fZ>if5(=>< zDCocr=93!N46Pd3b)g3+B8Y%|h4pUZo!VC(MxyMV(~cNcHzcHGI5l(u57_Nka>WY~ zWeUQW^davS5wtVy8#U-G4JH4lq`pEp7#VI95nIil@jtvK)N4WmuL<>NZ+P&2iR~CGPh7(hT99yw9R#$HUo-`l_L| zztUUMe_Snrd$|sm+Ld@-xc{ntn#bvw<-OK4oT+JwOQh2>>lk0OS%S<#@$QR79O;aN zv3LkGt#}EZUqx9?!Jx6om+dN1R^AR5{eU2J+L8*Il#KTaxUzMg)l_QponEcynWGm+#V#2^7i zT7^pq;oLIpTH|RQm!5l1o|s-vzwgG8H|a`JwPP0`+jk|`wozk;?-)j!m8Y_}g=WoF zXc(M^m^J4#FE_ZS(m4e#$~2u%R8?$AqO}187DhZH`WER)QhLZ8qg$FJ%NE+TrcapU zEUyJr;iphtTU1hqbSKulsCYf-vLQ0VG^*(kPsz=;4z+)NRGYX+bxq)1kZPKDLGmt0 z-UX?vuXjN*&AT8ykqc4}PC+W;gHGzu>>H#=*~=zlCHIb>l_%8ZYcZ#Ur+B{698-i| z(UaC*;L>`FEMOq6F%_TDZ`oI2(WT`2DB@@)XTZ>NIqD$E2M57ml@EgF@QMci@Bfnz zzJWi?>Cg24=J@|^294vsm+8;*kThMtg;{DjMZqgpRhJ{!U^1;(o?kXb6?R_MawZU# zU)RpDDF=skVNMr(xpOSJ32tPenJzro7xrT;hLicc1;2ITp?1xiMlOw$)AIo^C})%4 zm;0pUk!5M*W9aCegPL!_h$zKt;bn+#jDG9L8&U0Zaqy%e^MwH!z^ge z5uqFB*;T;Udi4~#Z-=yFWu(&d26)*jM!`GLRm~KxT$Xfhj1VaMoj#*=KWpjVZPOig zZl3yNAi1?CS04uN(KofDPlw@_g;6RupL4*ik3;t4pYU;M{>BrgWo~=Ia^c$^F|D}k zXgJ5$2}jleM)UbGliK)Re2=cBz!@AwmO}Kw!FQbwQ-xyQm zTD7BMH@Irbo**fe7S(b1Ih?K}#_b+TFQEvb&_SUx{ig1KAt2phqCDRzD+6(Br>?VL zUmJ=R;rT9Gq>_xgJ#Cmb8jt)qZM->CnB7`34{5BUla3keV-kxI(#;J9Qkch}ranur zF>;NSx^L)~wcJVHsJoCcbWLHdJy}xmDRb_Vd`U z$3u zu*MyiHZ)a*&MEFQ&FYrTQQBNkW_t=TE}}>$4<-Z>MO#ziBd?e)s>zF^2ESiBK^J;0 z{#;#sPG!48QS18GMG@y>IlXyPgd(s^#MO^v>Uu1*f%;E^h=K-rH4&bXB?*{@3h*wbV{$!_is1mQ`S)G)0fylz9@Pi&*oV! zp^bO)CR!*T<8WDcw00?$r2B`SK;F)i1k(X5@qgZYj<6O29^r8s=I~egOD~X;3+xk4 z$}a}5b|Mit0>Z8^0S{6Ybv7`C-X{rqLC7t4A#~gQ1}B)Waw-Usq{$E%-Q`2=3<{3$ zA2t{_o=iY`V-Pw4aB!#*<)( zNO!2dT&DAuz45Y9wR6HlbBc|fdhj^gXp2OX-aT#!2kvvU)+Py!^0NOI(i6JTzsqz@ zBOp>(Mk)?Vzo}prYnYa)7B~f-HGCY(Dx2{9Lz%!6XRT82gW&!q%_VU%#?S%$*WjSl z9%Mi0!AUYWFcktykJOM+a$OnFZ-Y%3fo)j6%9R2rwcn^U7P0oCR6?yw3{X!jp)7h~ zI6VZ?FK6{IYQaXli@L@jNw$vu_J3Dl_CN`H3zBL|BaN*1H*>?(eXlF=B-^Nou~Y{ji$@<8sbV$vZPhlnYDoL>%;HJTzY$ z$k6`nl9P5|5qR9RyT`!}IqKc;)DAG?@YU`Rdj#J4k-6)~&<-i}G2j_V5cXe>%#M`f~;nTbM z^P`&-VO)HHY&qo~sQ7^*e=Xy{Me?we$t01u*C<{?%n!9%1XCOvIy$oD9oM{V<5nHs z&Yj~iQ$$l^DH7=yh{aZuX%u4^k}fPN2{Zh16Hae!;Gyf56m;q~-LkW0+&HW$3RvmX zT!xbh16Rjn6yl`sO1{PEB*%iOeb(YEsv6fFR?7`xh#`PO#C411g@H@!f#)OQM-4u3tZzW3(I24Rb}BY;37^Rh}a_Xik2kBh`cGY zPWK}-V>5+(vtax5R!w}Mej8}>)=M143m$twx|s#P|NfPoT2~I0 z>lCoTr*Hyn)-C<@UjAFpR(y08-bLZPik+}lW5o~13g<`U>1!<)_8OHRI62@1|N0m3 zP1ATa3xmO0ZkDT69AmdZFoNX|@2w>kV@S+_1C7prb;L^O1%mjW;Qy|$C@pPXH_G%G zjODhL1V3Okv5)o7KdDw-)L46%vUZ@>G?ci;Ufc;Ph5hHZsuO@rW1AU@mx zd>i|9{r-hE^}3MMJ=aeRJwikrADtcN-xPn95099QnizMyQ&s{aOc#V#E0HNGZ~v+? z5q(9m`N0uoQaV%b{uudZ;&8vR<44wFFL13ST9uY$b<^(vJ1*0Iz&(YR^*=!Zb0R%| zW&Nz4f&Nbgf-WSZe^*a+G=&HDo?-wC-!@kWW*jsA}@BOpyXL(y*izi!j^C zQ5vu2Wvca0;K)vi8We%1I!Ygfe|YBe#Tv~z{OQdaWuMu32TKD>NvCJ(8^C+EnLNxvYjSnOQDu7T+KTsN^=w0Y}fR;4^?>a(H_3@w@ZN z5A}jWIrD`jCBWIB$#}EnGB-6wL|Zy0n=H0~HZ!D=XBULTv@XM~awIJuf$}lA2zT#f`YTbt&i^ z8NDpmiXg>zkV5D>iGDMqo2X}EFO~t_T7;&mi&1Cnor?z;2=9rl0VNB>KnygR}H=c!eVLZ;G>!HY|H^4PdmvGu+0QZnK zlgKRR^V!#iQ?2ESYuM?!R5V?O^;TtO6eWvLaV9DWcX0OR{K5)c$8(cMWZm87(?ZAs zpu$XkX%Zd*J)rD|Qq4!)F7oJe)as$273Rx&tK<<8Vu}x5AiAhg1D_<&YaYf&qAthg zj?WIyC?Dd1uurcknzdPxs7O`gaa$M$6_lmd2pv(1Ei{KM**`nY7|BZ6g)F zS%&|9bN-91{C$op?%UUJY}aUy7^(j~ibb9y;j7PmggWKQK#_Dr7I0pq&5|ngA``0B zm6Tz~tzAVi(oGo3E&~B0>6${WYA>DOs}pV?Oawg2fh#4W>(58QFFMhVsT(ynDZFaN zW@JO1M@d(gE=`oU4Ig4S9F~{%q3T?0F_*B-b^5OSA(@(j2rFb~ijO{G;6zuxG>(Ub zUh_|%4j0jfvv+J~6tk3{J|XoBK4fvV{1EMl}N`Loay(fjPhmBm=ra3y^^Jy;p6TK0iz>;)hXP2|p{X60}?#RPtx zlPoEDE8S63st)mmQ+^U`PDuhNZ|uo2C-kQTHC&z9cm+N~AU-$gObtGaI7wBVqIiI= zq8h8oGSRy5Vy#1AUs}m7>Ky8NYr~)5obOqoYfd}JIWMes{mdk(zbvGLrSlv~E3dML zOShF$UN-xx27mu_L77rmGhLNmH;!F?-sq|$6l8NNc?$Nztm4u+jy2aMJ(5dpT~J|e zGy{?>ofEuV4;O!#z`l^|v1X}QiFJx7gvc&R6gULoZd#q-LirCWI~*1de$Y6kf?b~F z!6h<|O1e`dhV~wur}R3I*FhD(7P(|c$tJLuq|Ocx2^NyVN-&^nsksep7};6L6PGB{ zHLrrUG+dJqp8(0u8L?VB-9m?Tu4Nw%*Qe0fRZ@}HY&JN#P9zDt(h7v7ewa#KG$aiX z+^6z?>np*JnXcO5isi|9cLaH-z}>urS|11F(~L-d37fB>e%mZBEY_()26)g@ewfus zZA^bq+auSxK#}c1ieuy1{wPoV)PR7yyif~Vi6`YDJ+xfPpi(mn`8ct z4U#^%W>x5s+Lbs(PxbyVRL`~M6EhEn12N^VU}yweMpsLk?C8y2D_gvCy_;v+BqJkI zbUy7;(2R;li-khiV9XS43^A^q-Lq)JtdFt$69Ihb?$I zwdc~AL`xTp6h7ECIibVCjIN>xwO!~L#u*aErRu-jC6@==)cI5T+?=GLH^}3C&^ZVBBGj3KaYcrxR)LCXa5!!B|9GIt6v=zBjtJjO;lC{102i7v}u9CxO z8f0Sdk&?i6^rJPqLlCMB9mu$RIy%xk4J5W5G>5eojs2=Qq@a}qDA!c-oJL>h<@$zt z%i6+5`n4<8p_XBAS^{^}oMv@{HF7fEt_R}dIsl*r*yNqgS6B%&H%EVfR-M6-u17KG ztBek#ikj?brtSw^+>|Jt>hhLYZ+k(lREAT{vg)_k*46eEZ0OgyDnMuxF=;HjQ+6|y zece1e)i+0Rx|;Rk*xBJ>Shr&BA1O8T!m=MDvWI_@(86n-d#{<6odT`o|~^Dc+~=8L~7Ecd_zZCdc7A zH#&^%Vn3^#5A%x>#2Mcx7&3ZVPI-gCtm>6(QBf%~WU?58vv`jjo4aA{ zZTN6<%yQeV-4qh&!(t$BVe<--@>;!u#4AWD-JNvEfL2sUSU)&QT{@4aJf148)#E9T zrz+id^tXg^dj6Sq*jL}hc$kWBrI?{D9^b)HUkz#1} zwy_%Go*7;G>D*2I0R0u}QK?iOT?f&X-5hljb~HBzvZFSf0^&lvwIX|1a}_jtf=}mN zRspTx2N(zW>{hy1%Lsl;Dw0924}h?M@ZCjOnqVrs4iPRaBJOADG#|kfBQY1hrO9ZT z&c`s@5H>Ts#tc3(;vRuJyk5ZpjP*IfISrxb=w>;Ozm~>l%uP467T1GX=AZYS)!P_a z8MsdJV%0j|_bOU$AG)$;*>7+k_W=`}<^v}5Dty3%XFvCz{e1d>iKmZO0CMG^DMi+b zMRH}Eq!_GVsVyJrnB!fel71B)EA07ns{MXS0gj;dl_kEcAIDy`MyDUYWr-5=e{R;mg43Q%B4cdh)Ct|aUwouzRoV;AUO zhi5-qiQ(isswx_#h%WMc)hc1I)>@MEM3h5s%kv$K=jwM^9Q z`=|Z>as`r(&J^YnVme)uO}W1Hq|=tSv8988)5c2e-&R?8d&g63W8b$Q-IUw-O@PF{ zzqE;umwyl!KZ572BY>crx~-U(dKxW6Oy6~S_;Q&QnUnUUQzNi0{t=w@=Nd!nN3@Wu zjl(8>t51=Z$!KjtCHIWM>XEr}qK#apYWED4^Rn5D)F#(s9~r1Vm?!5Fo(!f*q6&El zHpDhZ)({@!c#IQxjN>uRR^1Rqbfwx*uz0=3iE%kWjd$uE${|KPmA5zuo~!MDgL&Fjap^M31(x*rGE4;Wfd_^oJSZXj`pos# z#8McVY3uJm&!+xv%)%%#M%PJU(p{vp;CUW~fe^DH{Kqg-J=><_NonlU#_p93boAEd zZbo<3%g~!{XXHz_^5iO*!?_a4T!S(S^Xq^^V5=Q((|yt4D^ zz*gGl8W)Dvu_(D&MNdElB=y5}MSv-=a?flFE@`K~D-cAc~@>f|9hw7OZRgn5ne6avX zEYycAW^YOA5+Aed2}f6}x3Q@%_Db9~KFCTz>f6vhO`%kKuKy;v}Od#oykF1BhX5!b;=c2{3tZ;J(R9oU9= zuI)UWixk;LlQ|C+Z}g^*^m@9;8-tajE?on`*8_u0~D!y$Ix_#buFLisV`wz}( z^e=UD4S$?mK07DTh1?}-$u;>TX@b4AQE%m7&%^xh73*Y$bYYiKaI7vGULc*+MUsBX z%ob?`$BTa>XV0Q`{8S%~isCe8a;^Q< zXk@=xgWJ_4%#v`~jLS>E4y0w^t`)@mGMRVRP)?bQ}f)F z>pnbpRgAO4G)M*wd*q1CBS+p=JaX(|3m!S{HF9)FA!=K;ow#EX|8j*GtG+=s(SOeR zw9S)Vdta}*=6$`qub21r3Orq@w5Rv=Vs~9~yirQmf{NA3=sWs&EhYw;_#O$-BotYg zZRR!O#gf2_C0;DqVhf&p{5yyx%#^V6bQ%84IdqeqNd1Fr6*;3R>=NxYiB2hyeLF*z z6ko!OZLX=f_+sY6t`?MYj9s zkW4X1v48+~3@gK0Uk8(i&aUixI~BS{veTxXmFiZ7pW&@0A|9%HFpARg-HXwy(aSN? zEkuDI+_08>3rn`$09>@MyGnI_@3UH;!&Gk4y!G3T=*z3Jm3^+UJ&O@e~_UL4GHp}Q2j4p92EJ#>VAl>KX(p!4gt7#jU#P2-qlo&X*Oc9TWsck2 z=hWU+`%O5x3c~qf`EXG99~apbmDA=Z_+=rpyTs5B$FHQDE57J_R3e#;0bRkc86_vt zvRJ-aEaJ$jCxDm^ke?3qHi-twSA;${vp%XjZN-C2*Yd&&S|Y~_m!+#~OzIExei_}B zl8E$~3HS;CA7%&xcg6gV#kbn?%oT#FHU6t;=r%A9lCr0lA zC-!E&!?dQ;PF%E}D0OOZs~RHs<>=&C#Yqx}T_iQ=EgvtA>$KDlY9S&~vGa13)u0IF z4)MrYZaL8-q-&4>?&yWE*;au+P3H@dE$3moSm1(Ej*21mg^`s2thwk=+JRq6v3t78 zZ#wl#tiuYEY4$)H>F`-~+438EP`zoocZL+}4n&}paoB+7Ng!e5;qJN;d`OfPkw(my zn#dYP3l$1+c(n{Bu}E&Ewt(~)u=o{5VMlR$L4z5VoSR2Us8q?eW?=-&fx}3ZHbQeS zs;YI7Rv%~>X?I#DTGK4F9U7-@!(h6w5*SP()Q`fea$gw7*st2iFi2PVl z5Q!srB*a%}@D&<-g@(?qzCweq(6Cn(8VJX;(eOu25e%R7EH80YhN+jdqanfCBji5m ztVMg*Vz=vr92yFM`48HYRoJFeQ5i(?YAQ&^6YWY!>DFnPg5OmDF& z9XydaO5Uw`q>Bb{r87K0Ey(L&p!U+PiImNW0^y+Th4^&a1V#uDyK3J|Gm2f%BF$PJ zE|*;XWwluIU$cRqa9rkObF7=OX)Z-B1k15&x6(7h1gnu&62QB}N>ydZs(0E^Lbqsj zk$!xrNx49VzBOs@5qp4al@gYsdWTYYu#7AYF3E;()Do7E0DzYwk(C61m$JN+<)thy zW$nU41UV8$H%Vg|9eG{{4%>0g;m5dQGOyn{%X#tcoPJY*YI!huAcZJiH<^3Nj$=Ep zJ&5n>|SCSbzm=^}3{ zo-X#V1y2|Enl3(qtWyfQS(kOpQ7L)HA}ls7S*ETyF|5~_Y)oOWdDO| zy+)nvuK&F6om>C=eJ!&tah=7X8};trKV7KQPX-fqPx9$v{L9Jl(a!ntBE-7v&a~46 zQaVO9sF}0kGgpb)w!PiZ{x6kYaA6U#h0HX1LLCPUptbRrH2awx<`RRazUW+w2E>Jz zo+3P`-_#C!q~$B1hmZ;9i!>8J$JQawp1kDD*y!qLl8DXl*<7yqtX^{QOi(HTB?5e9 zqzG4Dn3rUUyF@aG=+dZ9x#RC&(#7!eBFYFO0GUja+2dWOV&-5O5!-@XEG~h4v)Gfi zynTn8#h$LW8~E}CR*zU=+6w0PI>}I!EWdx{bZ6j;@VYe?rf3_LB*#`)ilsoqgjOsG zVrg-5!XhvgY|n*_D~iSDjAqw%>F_qNJz8p8Y$Gq5F zWE^adoA$QYl_M~m<({>@IX;?wm4C4HB?Hk|?x*3F5*HggEpD+Qrk2V*L9c7Ma_1#E zJFb8nxFcDn;dJH#pnn|RtNuXhS+ELw#hPwVZ0L*P#11P}6ROG@ zd27xzhnDB7c{qZv=r5B9b$fy}(c30nj}BeTLrR&bQi!H;G>v#lvOQ(mlt=IyR7DFY zkW*v35LaUybvgv;MU0vtAxUsi{8**LPFG9GI`XP+ToSIi)FH>}4bu#15^Az#rjXf6 z@Rtc}YQ|+c@goEi-1a!kO3Gr-PkMgR^OK&Rbn%|rz?`uqx_?a5M}wN*#`FiZJrq@v z+#`}38_)JccIxMq1;`DxP>HH}6iAM!l^`WMA|l36?1V)4;)lNYVf7PV{Lpznp5ztd zd}+lGT{JUB5y0rnh!ke8GM(enLzq5}Vy15YJz2$Y6TK^A_R%lj+&#@DAW&J8QGR0WkJWAVsW~jxG~SWlOYvTc z_biR06t9Wvu28MXAV;nUgxm-r(%)*aVg(iMl}Ex3VyX23^u?-?w0h2^pk>ri`m~)l zgC~Z+k+Pkp?9<-0NgWpEecUrr(<7OA{F<7*kd{ZPsL8w@`$$UqAS2ERock%#%qbr1 za!go2$toi}kwu0z8Mza2G(!?%+u`j51f$>=UAMM%nyAnU!2p<7FEW|mE-p^b5t%L1 zX&S3E{|k}9;VfnOk4W7L5ENP`S;Qb((0FDz6gU!qr!G%GTHH{Us?8tZ0?k3HPfKZ3 zol|gTQM+!_9lK-Owr$(CZFg+jwr$&XzK-p5?40z!_daKzi&eF1Ue2mjHQ)J+@hq~9 z+PE>xyud;OTWG6>6oE9*G!3*UHFpo#lCRk zs;8@7Bwed>aFY{1jcM+tG(4=>fBz(3~os zbNtNSs3h+9U+4N6qxQ9TDcJ2eb&;b}5r0pPt-3y}ft}LFC*&xr-H&V*cGToD)Y9&qO!cBT&s>Ss{#`e$+zQ)>Z0V z6aGDiz3jfDlwLs2TdGnr+Qm%8x@in%HfaW88ZO&mbE3efg0HTWr=}RL{wk z^4u$eNrJsS;=kkqFDeXo)iZ36^u?d1ZDd2?DP^IkoP{2xK#ns;a!^@WdE#`AJjSdO zJb4Ps>zh6DOeu9Nk_@d>0(D2COf#&L#mHDLiNn7;HUbNW*5*P%A{_Ar1bKmEIHYpEZD@VZ;`lKVNINd)yh&c>s?q6=HxM924-ax0X_= z4+R4#P^7>V%fI0wue**x2$nek{hN~la|A8l`vGcQe4L@-@N_RV*_t)s>_*qg*(7l8 zaJw?uxipubxZMR$#%AF;DJlIW@#rEcLlRfVUot8lKF1vuyYkUYl z=i#N&pJ*O~T-0@S5?jt?$??0Ery*k%*W)sN6}Oxe1-{x2FKt0QLcLU4yB|d4RQ6ql z))??1KFEPJX-RtMliHn4aeYV|j5%A@Nyv=T%+hB5n(L8aA3!4o{levK-1PH?QdNV{ z!Ie)f$HhJZ;Udz6Q_Y*Cf?R>jPt|c)vBe3_FY|V;u2?hI57#+(yB!m9y`WO1K)5w) zESuQnWFIn0NzfgZw=IT$;?i>g2F;}h@8_(jZh(3Ixe%>RGVoylY-V8gO21S?0>8Az zW$i^`bA_-g-0_jX*yHy|`(ZVU&FT4w?d<%q=LO3fGP?s7>2`zm=c41HFi=b{CqVYb zlq<=>XG^^v;ZFj-tStHE51}+NCY`?;5zyx#!O12e(?5U%-e1{y-dR!?iY(TsCj(4pv^6ExP=iG+2 zH*ew~vp|1^-HlG-m#`ZT@Wu^f#}|-}RYt`=Y7>9c3wfxFpw7PeiFUIluvj$aJvQj1 z)0s{}!~&$kX}a?wr4i9<$t&Ro9OSuE+)L@BpQiK5CI}7c%Pk?2gzSFdS-}g*iIyMs z_^)QdY0AW_Qf@JUza1v5DJg;nHnNIQ1ZVIY7GbW7R>wd(=;mcBYtK%FkO{$AXU=-C zcq{K3y0@$Sj7%Yv%FR3dKY1gZ?nak|l_;Rspq~GQ{*t!CtWJca<1q{FEUn)FNL>wR zp+_6?*hkddgZ8!_y0a}HJUki#&eyZCB{5w`rIoo(d#%jf?dzd8=j$5b_e1U%2mkhL z=zmh(RXdxCyEBJnUH^@jAwlT^_5tut)(eG?*!O+_TchjvLDjw2n{&hd<|JfR$YalB zDci0#@+g=&IR`h-%k!qkVJMU$PXc#XFxmXE3MaVKldB^;JRcpy2}jB&9w#vB7Wbss z3%?4Q5^aR40)c?8(gC@zM20{W3NgmMBI_dQJq7Cgs3-U|?Qb{(d3Rn+%Y1Ljc82Tyj>m#!uN1E%{B*k{I5!;iUykw2iu(G~F$*yRyFX&u zo9#MrYa z-1VjesMmzu`cL4=3TTY60xbn!{o(LHMRenbKuC^f7e}h6Yt^w*pa5vrprZ%HIyZvU`zm z{Pmti`yUuBuDy?lPj(RdQ_}YoC&qESGoS!F8&{I>Fa9u-R+YA`A^}#IkezGh{Y4!qEUzp{RGWjr%X)4Oph{g z$C1%!oF2Tu#G(9A?Re!Ul(QYpnCNi#_8S)!qboG*GxY4ug!B4OyHp9SdwP`a>&4r= z&7FTe1A16Yj}S88FmU%G`^x^-R&HCfkvQI|zR&E7t|;i<@ONrXzdF7MN=A#Xk}0cI z+6*LGQWuadG>pJHhN3V#e@K|@;2)LWASg&<`~;f`E9~g{Kwm6*-ZwZ%8|23J2{6Py zdO{E(82I7({JpTOX7=i>3CrcqI6pkI0P6IM0Q%kPtKir{XS=Ed*s2by>;>aNs(HZ@ z<9OviPAR*++gV?RXs#YHE6-X@N801_u zsj4+>?5Xrb?2%B4Ze@WZ`Af;FFnWF`_yR2t_NX+U7&xq~TxHUr_J;G=`(63gJ03R3 zi`w2THwN-(>D;jiHMBYxO+Z5kgS&NI#PBL+WZ)8a@fB}Nfq_Mse@o>;BToj`xq6=R zbtmL<$0TlrP^F^N6)FE98xSp^1R$#AeSte~aHfJ_258VSp5rE>cG)ewG193gk||v` zrj{uL+QM^T^Q@-yxS;Sj>BcIH*UGIcODiC_I9^ca?wn1HP~Bim?69*u)1P(kU0&)r zMWwuZARVXw7bkG|M@qvTsj+!i&VJ^JTGqR_p_R|)h3&4(2ej?+$Z7QL&tELN{^OYK zyFY(>e*P&`^P^J8c`f%rXd5|-?0X@!?}5fx7vF{=F`t*@+!962gxqRY1V&bUe+ zwK)^bPXprB;Q*v$O`T=();^*khIec6tthcLUTXoPF?ukr+`}MUxFUvk5s8c4_MGux*E9_sc&gZX8+V;=)EAj1lNLO6DHd+op&vOD z80CjrR+Opg6i8%iwd21xtwf!UalAE7S25T>_ew%xE|KjhvaQMTp@_0}CCD}|RIsv- zkb1v%k$M{yXO&MxwA26`_4#_o6+nTqL&h{Ss;v!rg%{^Xk`+Di;Zv_S#4Zy$6lSY% z=?ld8)PXFDXjJhocuj*&!YWt^NRr!i<+R-;5PDl z_K71*iQL=fa>fE||DDc~T>mGXl`U>-p&*_M9p>LEI%Z)!Z1#+fS{+mF;G(FO`8F}^ zlRBJniUL3^okT-3f~(KU-$0+_s(+~!wh;MVU?=v+QzP+#5YDPO2{WicfWFctmcWTxYG4jB0LoXiJAqpg zw@QG|Z8Z`=Xhl*_MYRlebiuyU+yNcZ%SK`ejPQ3Laon`vPI4(E>H0Z>#}JVO9_m=$ z018n<+TT)0Rb;#&>mhaNyDpqPUKEKJyTRDHwL3qf9yUYo&;@7bryX&9X?Q?zZ|u4X ztS>r3o~jS6>lm0dZa@x=s-ojgRIs;sd(5Xl3i?O4#hUFiVlC$@Zxm>9Ot!sJK28fY zb9l=@#*zbFG1e7AIm;4}i6p62=t_F)fjM_-NgFd+X$p68DKe{xDaIZ(idLwaE{{+| zbQPNZqH-^q!*{)==goXz$rZqx8nqo(7Ngg*M5tOjW6 z)bW`hYyak{Wm{9d;snZfi8C#Ax7!b|aXuK5g}<+w^7tEitD6z;zoV6(n$#W1#ZvbqC65Y!$LKX zRx!eclzVMhu-V%AhjeMho;~yfHaOyug9ieIqCVy$K-E=v+uabRFw4JDAYf)1CkMz^ znNla`rIXc#McX-ezfX25TTt!p7G~7jJ^7mkWl%}5zSdpx)Ky#(yCjjWqAZmhz1hN0 z)kjF|w0Uw&T?EGGAJAKx>>QGe$~2+bBt1@G?m6~9`ET~XUtpS+b#dW!9mMRYh*AimqR+_S=z5RRUWiq-e+_5`Qc` zYO1I?DuN^_y1Ht$J$VjZa7 zv-cx{Sz?45&>unPQ~zD`7b-C%;E5SyA$FuZg*iOa^x~+$xFmfju88(Q8<=*-YDr9) znN)~U?I2U{RVd!TH?@NkXVT>VvPKE@Kp2pT!b|M^E$v1dGn$t~r^!i9y*O70Fu7?} zLEYN=`vc?$?lcmRcjAX^+k8abm1F4)z4bIeu*t!SY#l5?dsrYCuen?w(Ku@!t|)39oX ztzIs<-#Nc!k4()dZ^hHA{3Qo}di6qL+i_7MmIXh@>z%1|qM;7?f&PynC^OHC{rcEZ zUfehH3nIFHRq5Cn_=6XmSO@Nrzv!jyMrmO*&p03LTQO!f+y#HbMu;+^I|w39Cdg~` z|9Z*@4KK$z42Vzw>yF>+hQq1wgDu&Mz48w0HxE7%ndVWS*}HwC0Y~dpb`HO|)c{{$ zlL(WBNhn*gL;X(CN$^qZp7MLt=g`brNK#0V^QW-))@RqGb#Tk8^Dc@Y!!!#TH{9@p z{9)_AK8?yw`2k7XfN$=m-pd3Sr@NAK%BEUG)tl~(Gq;A+fw_3fjc4_)BH#wfZ90+H#h6K zxv!$QQOyFo?6pIK;iWk;f*WDPFfknbPlRLjHEtOCVM_y?o{-^cQe)&2l9*a0Y8z;E zPQ4g12TqJxk)){U+_4Dymb~QHn#J00IQg!%I zxc3~>UKi$C&|tQi#O0oD1u!4qim{To;9iuiK*JN8SUI5F64Ew@WR2s76DI|H1V|2s zD?TNLq%pPil4=lIYM*rCtA(>hfvE|vv_*rOGb%QmBLf(1o^J(%hT&{pVb`~xn?I68 z8D4XEW@9v8O;NdumD^?eb+ne<#Z98JdRUV55k?bd1BtOw#_$C{5^1 zC>%$ZGpuMU5qF0{**VWr z5_XX6*OvBwXp%Iciq_^Leo6gP$VB&~3A-Gch5_Pfrg~ zh_lU6UjFLmouLy+{2Hwc0!NVFo5UNqoietH{1@}FEfB0mVwDX-t!6&Y-Ir z4w`RSuc}r9wx#j#F>Xng7udI@(33clx&v6=CK*HGclj*=f)J_> z*;w*iE@D-2+0Q?4tS+Dqo2aa_%U(6V_i5Z~KDR?EYXuzi$ld5510rWs5qVSuQ<#NN z4f^@c*>z0%Q`s&hPf7hX#>X)$ru-CsvRR={fE?Wvin>%%lXmtVtU14^zgH@5!;S>n zcu1(5uLNsJYK<1jJ@-*#kyb-}MrkM}xz=W;8`RW+Kh9&@N#VhUM7IwxzZ^%DZt@n? z$WB;uyc#Ln7-PkwAq2wPOS?x#n8DfD5BSz8@+)vjzqX{5>!$aX_A>#^GkI1jN45xh zbT)G6bN!I$9vZ<0Nu|Fio@!0R$V9tk&H>#0$vJ-HZXKPC2{)cC6kX=FJg^xq9Kmhb zQP|fl6djdx&(_VYC_NIv@IkS>5-T!Ij@tmY{UDvj_~Eq1>VY(JcW%c%%|Idj^?6!Q z!K_lAN+L)k@f)=ulI+PR5T?p$kldh_5mLHSeBWF$Lx%|B5l?GGwcH2*l^6V)jqQIz zaGY?oEot+B8NXV?5*GH0cfr9ty@8Z=ok$$30G|fb6y)QzAM9Ta=&9Rx_cI6Wrpr$W z!QW;Qqho)uBn+wC?ssQKkOpD_l^F~6&+rUKLfPg}X82M{WNF}&Ah*;59(U5vb{IH0 zIqzW+**g@p2g>gkIk?9hY;K=n5h0U}%?@X+&d~|cAZ)vU1>Bvq@DW}Gx8IgzVV9zu ztZ&z1M(4m6qG|dP#^?&TA4kD!cw5#&WF~Oj36D2P!K?)xuF6>z+6wrAJZHSQpy~H5a0iz806{1}?UVgFd5} zaL-R!-Gj7x5H-$kYL<=u$!@Os?8+N#%^A#HRE)`mZ|95x6Qy$}3V;}-(up>=?_O2K z8rzu_%<#vx|5n(-BX-mg{dv1n54F9VNT9wV8ZVhrs4Q3>?3a7Q&GoJfI^BqUuUX|O zBi`&lr*k}fa_MB;PubB$l@M*+L1b*hJ_$yx$I*B^Y%8@IVwt6ax}nhVJ9Ty_KAk4R ze3Rz)3>w%bY(ZDBN zV~n9z9-$`w$Utz5^xkqr0GH;F!xksIGwP*5Y;?KTT}*LY7@t)w9);A?p<*x!;S#t) z%`2nY-bFFm4^nN1ZzC3TP!W+G0POVew+D()1-R2 zQ}z<;INat-r}U9!4-JFw_t5!zrzPtI%Z6We4zB`~t(6fiz7DmaX~2ll`f4_~{Pra< zwBPwlaj|1*_txNIqEGS1+1i+tU1~(SkyQ>22FO$?j%t*MqcbBaO7Xxj;cLfUf3?}t z)}DPO*If&8X5SEnA!Mw5gJuXxyT0ni7D~Pq5vW(qs1r}l`Csi>+JI5(p}Sy4rG&bM zaEEjch@4D*onY5yNd=C5Fp!KEOtz}Pr0|Bd$oKdT;F%#pvV`Nz;wMN>LnW|Os=-Z& zreSRn2XyXKskIjDS-!gz%gcsIY8}#D$FUO(Qa2nP+@Y?@J@~j2fX!Xo_mCGKPF(68 z=glTjxgu*%)&L;~LObjI1N+Bk;@qtwd=^#dAXdCKRwV8&)afL9WDT-s0-NFFpeBvq z8GI@IZ?s<=K704L2u6gqTsqk`AwbYuET=udj#~hGLQ+6Z!$j>#6s$AmgqQ%hR)l7@ z`d=uxI1=%XuyhrgeqnNi2;w;GLBW!-f#~9S6M}-Oa9PJ^xr3VxxDbT(elsTxm>OVM z)AXi4V%~J9QRc_%)Cv9?rLxvNNRbL1=(90{BB%*uwGGqxi!AoaOm}XQu%e%JQb-d* z-1pqw(9x5(%a)LAk%+<*;$$1mM|bhn@Wa;kQIKk=Z%*LSJhlbBjeCsBLR~J^K3Rs~ z8-#J}b{+$TkyScEli>f#VyhkO}eVeyTx^rV$xvHg-8$D7WY$4GBZuptl z?H)dOIDcO9(_WPYUurz;WbKly710I^RerAVFvpKNrnR!C{=dBJTj0mB`+lI`6_zWt+CZht3r1Cw|XKjyP#1j#gs&s8F@=pFNJUGX*NlF)IzdJj7er|

U@r}nz0LDB{;n` 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 z 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 z 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 Date: Mon, 26 Aug 2024 09:58:14 +0200 Subject: [PATCH 147/222] Upgrade vault to 1.17.3 --- hashicorp-vault/values.yaml | 2 +- tests/hashicorp-vault-industrial-edge-factory.expected.yaml | 4 ++-- tests/hashicorp-vault-industrial-edge-hub.expected.yaml | 4 ++-- tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml | 4 ++-- tests/hashicorp-vault-naked.expected.yaml | 4 ++-- tests/hashicorp-vault-normal.expected.yaml | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/hashicorp-vault/values.yaml b/hashicorp-vault/values.yaml index 6029a2f0..3b16a951 100644 --- a/hashicorp-vault/values.yaml +++ b/hashicorp-vault/values.yaml @@ -48,4 +48,4 @@ vault: termination: "reencrypt" image: repository: "registry.connect.redhat.com/hashicorp/vault" - tag: "1.17.2-ubi" + tag: "1.17.3-ubi" diff --git a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml index a17a6974..fb8f1c8e 100644 --- a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml index a17a6974..fb8f1c8e 100644 --- a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml index a17a6974..fb8f1c8e 100644 --- a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-naked.expected.yaml b/tests/hashicorp-vault-naked.expected.yaml index c3950b6d..49ea96cb 100644 --- a/tests/hashicorp-vault-naked.expected.yaml +++ b/tests/hashicorp-vault-naked.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-normal.expected.yaml b/tests/hashicorp-vault-normal.expected.yaml index a17a6974..fb8f1c8e 100644 --- a/tests/hashicorp-vault-normal.expected.yaml +++ b/tests/hashicorp-vault-normal.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR From c7105bc3b709b695bae263867f37b9c97833dd06 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 26 Aug 2024 11:31:38 +0200 Subject: [PATCH 148/222] Update hashicorp-vault to 0.1.2 --- hashicorp-vault/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index 87d3470d..09d48391 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure Hashicorp's vault. keywords: - pattern name: hashicorp-vault -version: 0.1.1 +version: 0.1.2 dependencies: - name: vault version: "0.28.1" From 86ad3420687b372e9ed01efdcf5cd313d5376a85 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 26 Aug 2024 11:32:00 +0200 Subject: [PATCH 149/222] Update golang-external-secrets to 0.1.2 --- golang-external-secrets/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 22a56453..3b3a0133 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure the golang-based external-secrets. keywords: - pattern name: golang-external-secrets -version: 0.1.1 +version: 0.1.2 dependencies: - name: external-secrets version: "0.10.0" From fc3fb1f70ce326b72e3ea365403143ce43a52342 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 27 Aug 2024 11:22:08 +0200 Subject: [PATCH 150/222] Switch to gitops-1.13 It is supported all the way back to OCP 4.12 Tested on sno hub + spoke successfully --- acm/templates/policies/ocp-gitops-policy.yaml | 2 +- acm/values.yaml | 2 +- operator-install/values.yaml | 2 +- reference-output.yaml | 2 +- tests/acm-industrial-edge-factory.expected.yaml | 2 +- tests/acm-industrial-edge-hub.expected.yaml | 2 +- tests/acm-medical-diagnosis-hub.expected.yaml | 2 +- tests/acm-naked.expected.yaml | 2 +- tests/acm-normal.expected.yaml | 2 +- tests/operator-install-industrial-edge-factory.expected.yaml | 2 +- tests/operator-install-industrial-edge-hub.expected.yaml | 2 +- tests/operator-install-medical-diagnosis-hub.expected.yaml | 2 +- tests/operator-install-naked.expected.yaml | 2 +- tests/operator-install-normal.expected.yaml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index 1d54b78d..753e4447 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -35,7 +35,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: {{ default "gitops-1.12" .Values.main.gitops.channel }} + channel: {{ default "gitops-1.13" .Values.main.gitops.channel }} installPlanApproval: Automatic name: openshift-gitops-operator source: {{ default "redhat-operators" .Values.main.gitops.operatorSource }} diff --git a/acm/values.yaml b/acm/values.yaml index ec3b5746..ff5777da 100644 --- a/acm/values.yaml +++ b/acm/values.yaml @@ -1,6 +1,6 @@ main: gitops: - channel: "gitops-1.12" + channel: "gitops-1.13" global: extraValueFiles: [] diff --git a/operator-install/values.yaml b/operator-install/values.yaml index 6a77c086..62c9943a 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -12,7 +12,7 @@ main: revision: main gitops: - channel: "gitops-1.12" + channel: "gitops-1.13" operatorSource: redhat-operators multiSourceConfig: diff --git a/reference-output.yaml b/reference-output.yaml index 54f4052a..1eef9745 100644 --- a/reference-output.yaml +++ b/reference-output.yaml @@ -112,7 +112,7 @@ metadata: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: "" spec: - channel: gitops-1.12 + channel: gitops-1.13 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index 39238f91..94c8254f 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -139,7 +139,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.12 + channel: gitops-1.13 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 8b18a4da..00cf4e4d 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -509,7 +509,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.12 + channel: gitops-1.13 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index dffb9eb6..5fea58d0 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -500,7 +500,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.12 + channel: gitops-1.13 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml index 39238f91..94c8254f 100644 --- a/tests/acm-naked.expected.yaml +++ b/tests/acm-naked.expected.yaml @@ -139,7 +139,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.12 + channel: gitops-1.13 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 1e2b1573..6823a01b 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1670,7 +1670,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.12 + channel: gitops-1.13 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/operator-install-industrial-edge-factory.expected.yaml b/tests/operator-install-industrial-edge-factory.expected.yaml index 6400a5a9..2bb7854e 100644 --- a/tests/operator-install-industrial-edge-factory.expected.yaml +++ b/tests/operator-install-industrial-edge-factory.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.12 + gitops.channel: gitops-1.13 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan diff --git a/tests/operator-install-industrial-edge-hub.expected.yaml b/tests/operator-install-industrial-edge-hub.expected.yaml index 6400a5a9..2bb7854e 100644 --- a/tests/operator-install-industrial-edge-hub.expected.yaml +++ b/tests/operator-install-industrial-edge-hub.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.12 + gitops.channel: gitops-1.13 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan diff --git a/tests/operator-install-medical-diagnosis-hub.expected.yaml b/tests/operator-install-medical-diagnosis-hub.expected.yaml index 6400a5a9..2bb7854e 100644 --- a/tests/operator-install-medical-diagnosis-hub.expected.yaml +++ b/tests/operator-install-medical-diagnosis-hub.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.12 + gitops.channel: gitops-1.13 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan diff --git a/tests/operator-install-naked.expected.yaml b/tests/operator-install-naked.expected.yaml index b6647318..d5f75c80 100644 --- a/tests/operator-install-naked.expected.yaml +++ b/tests/operator-install-naked.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.12 + gitops.channel: gitops-1.13 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan diff --git a/tests/operator-install-normal.expected.yaml b/tests/operator-install-normal.expected.yaml index 6400a5a9..2bb7854e 100644 --- a/tests/operator-install-normal.expected.yaml +++ b/tests/operator-install-normal.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.12 + gitops.channel: gitops-1.13 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan From 051cd8c3c60fcecb81ece3f79b760e946dddedf1 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 29 Aug 2024 17:43:31 +0200 Subject: [PATCH 151/222] Add a pushsecrets policy and vault path for ESO syncing See the README for more details, but TLDR: you can use `secret/pushsecrets` to push secrets from any node to the vault. This secret can then be retrieved from either a different namespace or a different cluster node. Tested this with a pushsecret as follows: ``` apiVersion: external-secrets.io/v1alpha1 kind: PushSecret metadata: name: pushsecret namespace: hello-world spec: data: - conversionStrategy: None match: remoteRef: property: baz remoteKey: pushsecrets/testme secretKey: bar deletionPolicy: Delete refreshInterval: 10s secretStoreRefs: - kind: ClusterSecretStore name: vault-backend selector: secret: name: existing-secret updatePolicy: Replace ``` The above takes the property called `baz` of an existing secret called `existing-secret` in the `hello-world` namespace and pushes it to the `secret/pushsecrets/testme` vault path. Suggested-By: Chris Butler Closes: MBP-641 --- ansible/roles/vault_utils/README.md | 91 +++++++++++-------- ansible/roles/vault_utils/defaults/main.yml | 2 + .../vault_utils/tasks/vault_secrets_init.yaml | 24 ++++- .../vault_utils/tasks/vault_spokes_init.yaml | 32 ++++++- 4 files changed, 106 insertions(+), 43 deletions(-) diff --git a/ansible/roles/vault_utils/README.md b/ansible/roles/vault_utils/README.md index 6b851f2a..ba26c702 100644 --- a/ansible/roles/vault_utils/README.md +++ b/ansible/roles/vault_utils/README.md @@ -40,6 +40,17 @@ unseal_namespace: "imperative" This relies on [kubernetes.core](https://docs.ansible.com/ansible/latest/collections/kubernetes/core/k8s_module.html) +## Vault out of the box configuration + +This role configures four secret paths in vault: + +1. `secret/global` - Any secret under this path is accessible in read-only only to all clusters known to ACM (hub and spokes) +2. `secret/hub` - Any secret under this path is accessible in read-only only to the ACM hub cluster +3. `secret/` - Any secret under this path is accessible in read-only only to the spoke cluster +4. `secret/pushsecrets` - Any secret here can be accessed in read and write mode to all clusters known to ACM. This area can + be used with ESO's `PushSecrets` so you can push an existing secret from one namespace, to the vault under this path and + then it can be retrieved by an `ExternalSecret` either in a different namespace *or* from an entirely different cluster. + ## Values secret file format Currently this role supports two formats: version 1.0 (which is the assumed @@ -58,46 +69,6 @@ secret file. The values secret YAML files can be encrypted with `ansible-vault`. If the role detects they are encrypted, the password to decrypt them will be prompted when needed. -### Version 1.0 - -Here is a well-commented example of a version 1.0 file: - -```yaml ---- -# By default when a top-level 'version: 1.0' is missing it is assumed to be '1.0' -# NEVER COMMIT THESE VALUES TO GIT - -secrets: - # These secrets will be pushed in the vault at secret/hub/test The vault will - # have secret/hub/test with secret1 and secret2 as keys with their associated - # values (secrets) - test: - secret1: foo - secret2: bar - - # This ends up as the s3Secret attribute to the path secret/hub/aws - aws: - s3Secret: test-secret - -# This will create the vault key secret/hub/testfoo which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files: - testfoo: ~/ca.crt -# These secrets will be pushed in the vault at secret/region1/test The vault will -# have secret/region1/test with secret1 and secret2 as keys with their associated -# values (secrets) -secrets.region1: - test: - secret1: foo1 - secret2: bar1 -# This will create the vault key secret/region2/testbar which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files.region2: - testbar: ~/ca.crt -``` - ### Version 2.0 Here is a version 2.0 example file (specifying `version: 2.0` is mandatory in this case): @@ -210,6 +181,46 @@ secrets: ini_key: aws_secret_access_key ``` +### Version 1.0 + +Here is a well-commented example of a version 1.0 file: + +```yaml +--- +# By default when a top-level 'version: 1.0' is missing it is assumed to be '1.0' +# NEVER COMMIT THESE VALUES TO GIT + +secrets: + # These secrets will be pushed in the vault at secret/hub/test The vault will + # have secret/hub/test with secret1 and secret2 as keys with their associated + # values (secrets) + test: + secret1: foo + secret2: bar + + # This ends up as the s3Secret attribute to the path secret/hub/aws + aws: + s3Secret: test-secret + +# This will create the vault key secret/hub/testfoo which will have two +# properties 'b64content' and 'content' which will be the base64-encoded +# content and the normal content respectively +files: + testfoo: ~/ca.crt +# These secrets will be pushed in the vault at secret/region1/test The vault will +# have secret/region1/test with secret1 and secret2 as keys with their associated +# values (secrets) +secrets.region1: + test: + secret1: foo1 + secret2: bar1 +# This will create the vault key secret/region2/testbar which will have two +# properties 'b64content' and 'content' which will be the base64-encoded +# content and the normal content respectively +files.region2: + testbar: ~/ca.crt +``` + Internals --------- diff --git a/ansible/roles/vault_utils/defaults/main.yml b/ansible/roles/vault_utils/defaults/main.yml index 4d263223..7759db48 100644 --- a/ansible/roles/vault_utils/defaults/main.yml +++ b/ansible/roles/vault_utils/defaults/main.yml @@ -17,6 +17,8 @@ vault_spoke_capabilities: '[\\\"read\\\"]' vault_spoke_ttl: "15m" vault_global_policy: global vault_global_capabilities: '[\\\"read\\\"]' +vault_pushsecrets_policy: pushsecrets +vault_pushsecrets_capabilities: '[\\\"create\\\",\\\"read\\\",\\\"update\\\",\\\"delete\\\"]' external_secrets_ns: golang-external-secrets external_secrets_sa: golang-external-secrets external_secrets_secret: golang-external-secrets diff --git a/ansible/roles/vault_utils/tasks/vault_secrets_init.yaml b/ansible/roles/vault_utils/tasks/vault_secrets_init.yaml index 35327d58..8a098a7c 100644 --- a/ansible/roles/vault_utils/tasks/vault_secrets_init.yaml +++ b/ansible/roles/vault_utils/tasks/vault_secrets_init.yaml @@ -71,6 +71,28 @@ pod: "{{ vault_pod }}" command: "vault policy write {{ vault_global_policy }}-secret /tmp/policy-{{ vault_global_policy }}.hcl" +- name: Configure VP pushsecrets policy template + kubernetes.core.k8s_exec: + namespace: "{{ vault_ns }}" + pod: "{{ vault_pod }}" + command: > + bash -e -c "echo \"path \\\"secret/data/{{ vault_pushsecrets_policy }}/*\\\" { + capabilities = {{ vault_pushsecrets_capabilities }} }\" > /tmp/policy-{{ vault_pushsecrets_policy }}.hcl" + +- name: Add metadata path to the pushsecrets policy + kubernetes.core.k8s_exec: + namespace: "{{ vault_ns }}" + pod: "{{ vault_pod }}" + command: > + bash -e -c "echo \"path \\\"secret/metadata/{{ vault_pushsecrets_policy }}/*\\\" { + capabilities = {{ vault_pushsecrets_capabilities }} }\" >> /tmp/policy-{{ vault_pushsecrets_policy }}.hcl" + +- name: Configure VP pushsecrets policy + kubernetes.core.k8s_exec: + namespace: "{{ vault_ns }}" + pod: "{{ vault_pod }}" + command: "vault policy write {{ vault_pushsecrets_policy }}-secret /tmp/policy-{{ vault_pushsecrets_policy }}.hcl" + - name: Configure policy template for hub kubernetes.core.k8s_exec: namespace: "{{ vault_ns }}" @@ -93,4 +115,4 @@ vault write auth/"{{ vault_hub }}"/role/"{{ vault_hub }}"-role bound_service_account_names="{{ external_secrets_sa }}" bound_service_account_namespaces="{{ external_secrets_ns }}" - policies="default,{{ vault_global_policy }}-secret,{{ vault_hub }}-secret" ttl="{{ vault_hub_ttl }}" + policies="default,{{ vault_global_policy }}-secret,{{ vault_pushsecrets_policy }}-secret,{{ vault_hub }}-secret" ttl="{{ vault_hub_ttl }}" diff --git a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml index 060378bc..bafe490b 100644 --- a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml +++ b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml @@ -157,7 +157,7 @@ loop_control: label: "{{ item.key }}" -- name: Configure policy template +- name: Configure spoke policy template kubernetes.core.k8s_exec: namespace: "{{ vault_ns }}" pod: "{{ vault_pod }}" @@ -171,6 +171,34 @@ loop_control: label: "{{ item.key }}" +- name: Configure spoke pushsecrets policy template + kubernetes.core.k8s_exec: + namespace: "{{ vault_ns }}" + pod: "{{ vault_pod }}" + command: > + bash -e -c "echo \"path \\\"secret/data/{{ vault_pushsecrets_policy }}/*\\\" { + capabilities = {{ vault_pushsecrets_capabilities }} }\" >> /tmp/policy-{{ item.value['vault_path'] }}.hcl" + loop: "{{ clusters_info | dict2items }}" + when: + - item.value['esoToken'] is defined + - item.key != "local-cluster" + loop_control: + label: "{{ item.key }}" + +- name: Configure spoke pushsecrets metadata policy template + kubernetes.core.k8s_exec: + namespace: "{{ vault_ns }}" + pod: "{{ vault_pod }}" + command: > + bash -e -c "echo \"path \\\"secret/metadata/{{ vault_pushsecrets_policy }}/*\\\" { + capabilities = {{ vault_pushsecrets_capabilities }} }\" >> /tmp/policy-{{ item.value['vault_path'] }}.hcl" + loop: "{{ clusters_info | dict2items }}" + when: + - item.value['esoToken'] is defined + - item.key != "local-cluster" + loop_control: + label: "{{ item.key }}" + - name: Configure policy for spokes kubernetes.core.k8s_exec: namespace: "{{ vault_ns }}" @@ -191,7 +219,7 @@ vault write auth/"{{ item.value['vault_path'] }}"/role/"{{ item.value['vault_path'] }}"-role bound_service_account_names="{{ external_secrets_sa }}" bound_service_account_namespaces="{{ external_secrets_ns }}" - policies="default,{{ vault_global_policy }}-secret,{{ item.value['vault_path'] }}-secret" ttl="{{ vault_spoke_ttl }}" + policies="default,{{ vault_global_policy }}-secret,{{ vault_pushsecrets_policy }}-secret,{{ item.value['vault_path'] }}-secret" ttl="{{ vault_spoke_ttl }}" loop: "{{ clusters_info | dict2items }}" when: - item.value['esoToken'] is defined From 9aef7783fd35c4e6c7f8f1950f6e1674736bf650 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 30 Aug 2024 12:09:41 +0200 Subject: [PATCH 152/222] Fix PyInk warnings --- ansible/plugins/filter/parse_acm_secrets.py | 1 + ansible/plugins/module_utils/load_secrets_v1.py | 1 + ansible/plugins/module_utils/load_secrets_v2.py | 1 + ansible/plugins/module_utils/parse_secrets_v2.py | 1 + ansible/plugins/modules/vault_load_parsed_secrets.py | 1 + ansible/tests/unit/test_ini_file.py | 1 + ansible/tests/unit/test_parse_secrets.py | 2 ++ ansible/tests/unit/test_vault_load_parsed_secrets.py | 1 + ansible/tests/unit/test_vault_load_secrets.py | 1 + ansible/tests/unit/test_vault_load_secrets_v2.py | 1 + 10 files changed, 11 insertions(+) diff --git a/ansible/plugins/filter/parse_acm_secrets.py b/ansible/plugins/filter/parse_acm_secrets.py index 0445d96d..1c5148e3 100644 --- a/ansible/plugins/filter/parse_acm_secrets.py +++ b/ansible/plugins/filter/parse_acm_secrets.py @@ -79,5 +79,6 @@ def parse_acm_secrets(secrets): class FilterModule: + def filters(self): return {"parse_acm_secrets": parse_acm_secrets} diff --git a/ansible/plugins/module_utils/load_secrets_v1.py b/ansible/plugins/module_utils/load_secrets_v1.py index 6478ac26..8b89d85a 100644 --- a/ansible/plugins/module_utils/load_secrets_v1.py +++ b/ansible/plugins/module_utils/load_secrets_v1.py @@ -26,6 +26,7 @@ class LoadSecretsV1: + def __init__( self, module, diff --git a/ansible/plugins/module_utils/load_secrets_v2.py b/ansible/plugins/module_utils/load_secrets_v2.py index 05a5917e..46cdcffa 100644 --- a/ansible/plugins/module_utils/load_secrets_v2.py +++ b/ansible/plugins/module_utils/load_secrets_v2.py @@ -40,6 +40,7 @@ class LoadSecretsV2: + def __init__(self, module, syaml, namespace, pod): self.module = module self.namespace = namespace diff --git a/ansible/plugins/module_utils/parse_secrets_v2.py b/ansible/plugins/module_utils/parse_secrets_v2.py index 512f75ef..f88579b6 100644 --- a/ansible/plugins/module_utils/parse_secrets_v2.py +++ b/ansible/plugins/module_utils/parse_secrets_v2.py @@ -42,6 +42,7 @@ class ParseSecretsV2: + def __init__(self, module, syaml, secrets_backing_store): self.module = module self.syaml = syaml diff --git a/ansible/plugins/modules/vault_load_parsed_secrets.py b/ansible/plugins/modules/vault_load_parsed_secrets.py index 0a6aa146..f5acdc86 100644 --- a/ansible/plugins/modules/vault_load_parsed_secrets.py +++ b/ansible/plugins/modules/vault_load_parsed_secrets.py @@ -82,6 +82,7 @@ class VaultSecretLoader: + def __init__( self, module, diff --git a/ansible/tests/unit/test_ini_file.py b/ansible/tests/unit/test_ini_file.py index e92280cb..6c30fdbb 100644 --- a/ansible/tests/unit/test_ini_file.py +++ b/ansible/tests/unit/test_ini_file.py @@ -29,6 +29,7 @@ class TestMyModule(unittest.TestCase): + def setUp(self): self.testdir_v2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), "v2") diff --git a/ansible/tests/unit/test_parse_secrets.py b/ansible/tests/unit/test_parse_secrets.py index 0cfef1b6..2dab5716 100644 --- a/ansible/tests/unit/test_parse_secrets.py +++ b/ansible/tests/unit/test_parse_secrets.py @@ -62,6 +62,7 @@ def set_module_args(args): class BytesEncoder(json.JSONEncoder): + def default(self, o): if isinstance(o, bytes): return base64.b64encode(o).decode("ascii") @@ -113,6 +114,7 @@ def fail_json(*args, **kwargs): @mock.patch("getpass.getpass") class TestMyModule(unittest.TestCase): + def create_inifile(self): self.inifile = open("/tmp/awscredentials", "w") config = configparser.ConfigParser() diff --git a/ansible/tests/unit/test_vault_load_parsed_secrets.py b/ansible/tests/unit/test_vault_load_parsed_secrets.py index 1a449739..66ec6b69 100644 --- a/ansible/tests/unit/test_vault_load_parsed_secrets.py +++ b/ansible/tests/unit/test_vault_load_parsed_secrets.py @@ -70,6 +70,7 @@ def fail_json(*args, **kwargs): class TestMyModule(unittest.TestCase): + def setUp(self): self.mock_module_helper = patch.multiple( basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json diff --git a/ansible/tests/unit/test_vault_load_secrets.py b/ansible/tests/unit/test_vault_load_secrets.py index 12deeb3f..03d25d8c 100644 --- a/ansible/tests/unit/test_vault_load_secrets.py +++ b/ansible/tests/unit/test_vault_load_secrets.py @@ -74,6 +74,7 @@ def fail_json(*args, **kwargs): class TestMyModule(unittest.TestCase): + def setUp(self): self.mock_module_helper = patch.multiple( basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json diff --git a/ansible/tests/unit/test_vault_load_secrets_v2.py b/ansible/tests/unit/test_vault_load_secrets_v2.py index d0e5881c..7b934320 100644 --- a/ansible/tests/unit/test_vault_load_secrets_v2.py +++ b/ansible/tests/unit/test_vault_load_secrets_v2.py @@ -77,6 +77,7 @@ def fail_json(*args, **kwargs): @mock.patch("getpass.getpass") class TestMyModule(unittest.TestCase): + def create_inifile(self): self.inifile = open("/tmp/awscredentials", "w") config = configparser.ConfigParser() From 1ebca7f858bbb77678a4ea44679870412ff7b003 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 6 Sep 2024 14:59:10 +0200 Subject: [PATCH 153/222] Replace tabs with spaces and add some missing env vars that could be passed --- scripts/pattern-util.sh | 42 ++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 8fa4a26f..cb7fc873 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -71,22 +71,26 @@ fi # $HOME is mounted to /root because the UID in the container is 0 and that's where SSH looks for credentials podman run -it --rm --pull=newer \ - --security-opt label=disable \ - -e EXTRA_HELM_OPTS \ - -e EXTRA_PLAYBOOK_OPTS \ - -e VALUES_SECRET \ - -e KUBECONFIG \ - -e K8S_AUTH_HOST \ - -e K8S_AUTH_VERIFY_SSL \ - -e K8S_AUTH_SSL_CA_CERT \ - -e K8S_AUTH_USERNAME \ - -e K8S_AUTH_PASSWORD \ - -e K8S_AUTH_TOKEN \ - ${PKI_HOST_MOUNT_ARGS} \ - -v "${HOME}":"${HOME}" \ - -v "${HOME}":/pattern-home \ - ${PODMAN_ARGS} \ - ${EXTRA_ARGS} \ - -w "$(pwd)" \ - "$PATTERN_UTILITY_CONTAINER" \ - $@ + --security-opt label=disable \ + -e EXTRA_HELM_OPTS \ + -e EXTRA_PLAYBOOK_OPTS \ + -e TARGET_ORIGIN \ + -e NAME \ + -e TOKEN_SECRET \ + -e TOKEN_NAMESPACE \ + -e VALUES_SECRET \ + -e KUBECONFIG \ + -e K8S_AUTH_HOST \ + -e K8S_AUTH_VERIFY_SSL \ + -e K8S_AUTH_SSL_CA_CERT \ + -e K8S_AUTH_USERNAME \ + -e K8S_AUTH_PASSWORD \ + -e K8S_AUTH_TOKEN \ + ${PKI_HOST_MOUNT_ARGS} \ + -v "${HOME}":"${HOME}" \ + -v "${HOME}":/pattern-home \ + ${PODMAN_ARGS} \ + ${EXTRA_ARGS} \ + -w "$(pwd)" \ + "$PATTERN_UTILITY_CONTAINER" \ + $@ From b8e62f28788e7bc942d1552a55a2cb67fe6bccd0 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 6 Sep 2024 16:14:14 +0200 Subject: [PATCH 154/222] Also push any changes to operator-install to its own repo Since at the time the folder was named operator-install and the chart pattern-install, let's push it out to the `pattern-install-chart` repo which is a bit clearer. --- .github/workflows/chart-branches.yml | 17 +++++++++++ .../.github/workflows/update-helm-repo.yml | 30 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 operator-install/.github/workflows/update-helm-repo.yml diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml index 4fb784f0..71d94216 100644 --- a/.github/workflows/chart-branches.yml +++ b/.github/workflows/chart-branches.yml @@ -15,6 +15,7 @@ on: - 'hashicorp-vault/**' - 'letsencrypt/**' - 'clustergroup/**' + - 'operator-install/**' jobs: changes: @@ -28,6 +29,7 @@ jobs: hashicorp-vault: ${{ steps.filter.outputs.hashicorp-vault }} letsencrypt: ${{ steps.filter.outputs.letsencrypt }} clustergroup: ${{ steps.filter.outputs.clustergroup }} + operator-install: ${{ steps.filter.outputs.operator-install }} steps: - name: Checkout Code uses: actions/checkout@v4 @@ -46,6 +48,8 @@ jobs: - 'letsencrypt/**' clustergroup: - 'clustergroup/**' + operator-install: + - 'operator-install/**' acm: needs: changes @@ -106,3 +110,16 @@ jobs: chart_name: clustergroup target_repository: validatedpatterns/clustergroup-chart secrets: inherit + + # The folder is named 'operator-install' but the chart is called 'pattern-install' + operator-install: + needs: changes + if: ${{ (needs.changes.outputs.operator-install == 'true') && (github.repository == 'validatedpatterns/common') }} + uses: validatedpatterns/common/.github/workflows/chart-split.yml@main + permissions: + actions: write + contents: write + with: + chart_name: pattern-install + target_repository: validatedpatterns/pattern-install-chart + secrets: inherit diff --git a/operator-install/.github/workflows/update-helm-repo.yml b/operator-install/.github/workflows/update-helm-repo.yml new file mode 100644 index 00000000..fa1d6247 --- /dev/null +++ b/operator-install/.github/workflows/update-helm-repo.yml @@ -0,0 +1,30 @@ +# This invokes the workflow named 'publish-charts' in the umbrella repo +# It expects to have a secret called CHARTS_REPOS_TOKEN which contains +# the GitHub token that has permissions to invoke workflows and commit code +# inside the umbrella-repo. +# The following fine-grained permissions were used in testing and were limited +# to the umbrella repo only: +# - Actions: r/w +# - Commit statuses: r/w +# - Contents: r/w +# - Deployments: r/w +# - Pages: r/w +# + +name: vp-patterns/update-helm-repo +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +jobs: + helmlint: + uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 + permissions: + contents: read + + update-helm-repo: + needs: [helmlint] + uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 + permissions: read-all + secrets: inherit From 907e33b9cf1645dc47a9abf84b9db17782f1c1f3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 6 Sep 2024 16:26:10 +0200 Subject: [PATCH 155/222] Update CRD from operator v0.0.55 --- ...gitops.hybrid-cloud-patterns.io_patterns.yaml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml b/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml index b3d769bb..2edacc49 100644 --- a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml +++ b/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml @@ -93,13 +93,19 @@ spec: description: Optional. FQDN of the git server if automatic parsing from TargetRepo is broken type: string + inClusterGitServer: + default: false + description: (EXPERIMENTAL) Enable in-cluster git server (avoids + the need of forking the upstream repository) + type: boolean originRepo: - description: Upstream git repo containing the pattern to deploy. - Used when in-cluster fork to point to the upstream pattern repository + description: |- + Upstream git repo containing the pattern to deploy. Used when in-cluster fork to point to the upstream pattern repository. + Takes precedence over TargetRepo type: string originRevision: - description: Branch, tag or commit in the upstream git repository. - Does not support short-sha's. Default to HEAD + description: (DEPRECATED) Branch, tag or commit in the upstream + git repository. Does not support short-sha's. Default to HEAD type: string pollInterval: default: 180 @@ -124,8 +130,6 @@ spec: description: Optional. K8s secret namespace where the token for connecting to git can be found type: string - required: - - targetRepo type: object multiSourceConfig: properties: From 8452d308911e05a279f29b2b9424d03ed79012c3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 6 Sep 2024 16:34:20 +0200 Subject: [PATCH 156/222] Fix chart name in pattern-install branch+split wf --- .github/workflows/chart-branches.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml index 71d94216..5ec0ce8f 100644 --- a/.github/workflows/chart-branches.yml +++ b/.github/workflows/chart-branches.yml @@ -120,6 +120,7 @@ jobs: actions: write contents: write with: - chart_name: pattern-install + # The name here is really the folder to be used for the chart + chart_name: operator-install target_repository: validatedpatterns/pattern-install-chart secrets: inherit From 35576f6a7da66ea2b0c7269efc1930fb3356549e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 6 Sep 2024 16:38:51 +0200 Subject: [PATCH 157/222] Tweak readme --- operator-install/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/operator-install/README.md b/operator-install/README.md index a333860e..588b3d78 100644 --- a/operator-install/README.md +++ b/operator-install/README.md @@ -1,4 +1,8 @@ # Update CRD -In order to update the CRD, copy the following file from the last released patterns operator version: -`cp -v patterns-operator/config/crd/bases/gitops.hybrid-cloud-patterns.io_patterns.yaml ./crds/` +In order to update the CRD, copy the following file from the last released +patterns operator version: + +```sh +cp -v patterns-operator/config/crd/bases/gitops.hybrid-cloud-patterns.io_patterns.yaml ./crds/ +``` From 83976a6f010fae1aeaa10b2e165e87b5f4eb04b8 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sun, 8 Sep 2024 20:14:08 +0200 Subject: [PATCH 158/222] Use $group.name in clusterset metadata Closes: validatedpatterns/regional-resiliency-pattern#5 --- acm/templates/provision/clusterpool.yaml | 2 +- tests/acm-normal.expected.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/acm/templates/provision/clusterpool.yaml b/acm/templates/provision/clusterpool.yaml index d95905f7..dab4dd28 100644 --- a/acm/templates/provision/clusterpool.yaml +++ b/acm/templates/provision/clusterpool.yaml @@ -32,7 +32,7 @@ metadata: cloud: {{ $cloud }} region: '{{ $region }}' vendor: OpenShift - cluster.open-cluster-management.io/clusterset: {{ .name }} + cluster.open-cluster-management.io/clusterset: {{ $group.name }} spec: {{- if .size }} size: {{ .size }} diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 6823a01b..f8c37f3e 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -165,7 +165,7 @@ metadata: cloud: aws region: 'ap-southeast-2' vendor: OpenShift - cluster.open-cluster-management.io/clusterset: aws-ap + cluster.open-cluster-management.io/clusterset: acm-provision-edge spec: size: 3 runningCount: 0 @@ -195,7 +195,7 @@ metadata: cloud: azure region: 'eastus' vendor: OpenShift - cluster.open-cluster-management.io/clusterset: azure-us + cluster.open-cluster-management.io/clusterset: acm-provision-edge spec: size: 2 runningCount: 2 From 68d731edad7c5492c76dacf7a6a804755b173a4c Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 11 Sep 2024 14:25:59 +0200 Subject: [PATCH 159/222] Expose originURL as helm value This is needed, this way when this variable is set we can actually detect that an in-cluster gitea instance has been set up. --- acm/templates/_helpers.tpl | 2 ++ clustergroup/templates/_helpers.tpl | 2 ++ 2 files changed, 4 insertions(+) diff --git a/acm/templates/_helpers.tpl b/acm/templates/_helpers.tpl index 8302457a..1b934e62 100644 --- a/acm/templates/_helpers.tpl +++ b/acm/templates/_helpers.tpl @@ -26,6 +26,8 @@ Default always defined valueFiles to be included when pushing the cluster wide a {{- define "acm.app.policies.helmparameters" -}} - name: global.repoURL value: {{ $.Values.global.repoURL }} +- name: global.originURL + value: {{ $.Values.global.originURL }} - name: global.targetRevision value: {{ $.Values.global.targetRevision }} - name: global.namespace diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index 0237e94a..317ed4b1 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -4,6 +4,8 @@ Default always defined top-level variables for helm charts {{- define "clustergroup.app.globalvalues.helmparameters" -}} - name: global.repoURL value: {{ $.Values.global.repoURL }} +- name: global.originURL + value: {{ $.Values.global.originURL }} - name: global.targetRevision value: {{ $.Values.global.targetRevision }} - name: global.namespace From 2ee7a0688705c886deca95c81871ffbcffeabbc3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 11 Sep 2024 16:45:50 +0200 Subject: [PATCH 160/222] Update tests after common rebase --- tests/acm-industrial-edge-hub.expected.yaml | 2 ++ tests/acm-medical-diagnosis-hub.expected.yaml | 2 ++ tests/acm-normal.expected.yaml | 6 +++++ ...roup-industrial-edge-factory.expected.yaml | 2 ++ ...tergroup-industrial-edge-hub.expected.yaml | 14 ++++++++++ ...rgroup-medical-diagnosis-hub.expected.yaml | 26 +++++++++++++++++++ tests/clustergroup-normal.expected.yaml | 4 +++ 7 files changed, 56 insertions(+) diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 00cf4e4d..02f2a8dc 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -420,6 +420,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 5fea58d0..62402c39 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -411,6 +411,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index f8c37f3e..0c826026 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1371,6 +1371,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1477,6 +1479,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1583,6 +1587,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 65344a57..12632e63 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -652,6 +652,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 1038e54a..89691e7b 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -995,6 +995,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1068,6 +1070,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1132,6 +1136,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1196,6 +1202,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1290,6 +1298,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1354,6 +1364,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1445,6 +1457,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 51bff564..bc751aea 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -880,6 +880,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -944,6 +946,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1008,6 +1012,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1072,6 +1078,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1136,6 +1144,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1200,6 +1210,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1264,6 +1276,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1328,6 +1342,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1410,6 +1426,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1474,6 +1492,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1538,6 +1558,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1611,6 +1633,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -1684,6 +1708,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index b038286e..a852051f 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -875,6 +875,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace @@ -951,6 +953,8 @@ spec: parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern + - name: global.originURL + value: - name: global.targetRevision value: main - name: global.namespace From aaf456b607a744d919d7c55a60cc51846d065186 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 11 Sep 2024 17:37:34 +0200 Subject: [PATCH 161/222] Release clustergroup v0.8.13 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 2bacbfc5..c5fb5466 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.12 +version: 0.8.13 From 16c2e4ad9ca5be0c16cda7e7894523d0d88d5db8 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 11 Sep 2024 17:42:03 +0200 Subject: [PATCH 162/222] Release acm v0.1.2 --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 3a7663b4..adb30c66 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.1.1 +version: 0.1.2 From f608f63ba88262d23fade035ff8c6c8bc436a463 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 12 Sep 2024 16:38:12 +0200 Subject: [PATCH 163/222] Drop schema required under the Main section The "main" subsection of helm values is only used for kickstarting a pattern. It is entirely possible to only set one value and then set the other variables through other means (editing CRs e.g.). There is no point on blocking this. --- clustergroup/values.schema.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 2fbe3421..08f8c1e5 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -76,10 +76,6 @@ "git": { "type": "object", "additionalProperties": false, - "required": [ - "repoURL", - "revision" - ], "properties": { "repoUpstreamURL": { "type": "string", From 9a8b7cc1b02d939d16c86f5439a59cb7e87465dd Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 12 Sep 2024 16:38:44 +0200 Subject: [PATCH 164/222] Release clustergroup v0.8.14 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index c5fb5466..23764f5e 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.13 +version: 0.8.14 From 47c59239ea454984ac0792eae9f077b0a848afa6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 13 Sep 2024 10:14:08 +0200 Subject: [PATCH 165/222] Update README for the v1 common branch --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 568a2396..63faddc8 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +## Note + +This is the `v1` branch of common and it contains all the VP helm charts. Please use this branch if your pattern +has not migrated to the multisource approach. + ## Start Here This repository is never used as standalone. It is usually imported in each pattern as a subtree. From 1138de9fce6d91874f60f8883a14115b5ce21272 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 6 Sep 2024 15:18:05 +0200 Subject: [PATCH 166/222] Drop all the helm charts All the charts that can be used via an OCI registry or via a helm repo are dropped in this change --- acm/.github/workflows/update-helm-repo.yml | 29 - acm/.helmignore | 1 - acm/Chart.yaml | 6 - acm/README.md | 5 - acm/templates/_helpers.tpl | 59 - acm/templates/multiclusterhub.yaml | 13 - acm/templates/policies/acm-hub-ca-policy.yaml | 226 ---- .../policies/application-policies.yaml | 179 --- acm/templates/policies/ocp-gitops-policy.yaml | 335 ----- .../policies/private-repo-policies.yaml | 161 --- acm/templates/provision/_install-config.tpl | 66 - .../provision/clusterdeployment.yaml | 83 -- acm/templates/provision/clusterpool.yaml | 82 -- .../provision/managedclusterset.yaml | 13 - acm/templates/provision/secrets-aws.yaml | 111 -- acm/templates/provision/secrets-azure.yaml | 113 -- acm/templates/provision/secrets-common.yaml | 95 -- acm/test.yaml | 35 - acm/values.yaml | 61 - .../.github/workflows/update-helm-repo.yml | 30 - clustergroup/.helmignore | 1 - clustergroup/Chart.yaml | 6 - clustergroup/README.md | 5 - clustergroup/templates/_helpers.tpl | 242 ---- .../templates/core/catalog-sources.yaml | 14 - clustergroup/templates/core/namespaces.yaml | 42 - clustergroup/templates/core/nodes.yaml | 25 - .../templates/core/operatorgroup.yaml | 54 - clustergroup/templates/core/scheduler.yaml | 11 - .../templates/core/subscriptions.yaml | 73 -- .../templates/imperative/_helpers.tpl | 125 -- .../imperative/auto-approve-installplans.yaml | 49 - .../templates/imperative/clusterrole.yaml | 37 - .../templates/imperative/configmap.yaml | 21 - clustergroup/templates/imperative/job.yaml | 66 - .../templates/imperative/namespace.yaml | 10 - clustergroup/templates/imperative/rbac.yaml | 47 - clustergroup/templates/imperative/role.yaml | 20 - .../templates/imperative/serviceaccount.yaml | 18 - .../templates/imperative/unsealjob.yaml | 59 - .../templates/plumbing/applications.yaml | 296 ----- .../plumbing/argocd-cmp-plugin-cms.yaml | 12 - .../templates/plumbing/argocd-super-role.yaml | 51 - clustergroup/templates/plumbing/argocd.yaml | 207 ---- .../plumbing/cluster-external-secrets.yaml | 43 - .../templates/plumbing/gitops-namespace.yaml | 13 - .../templates/plumbing/hosted-sites.yaml | 172 --- clustergroup/templates/plumbing/projects.yaml | 39 - .../plumbing/trusted-bundle-ca-configmap.yaml | 7 - clustergroup/values.schema.json | 1085 ----------------- clustergroup/values.yaml | 139 --- .../.github/workflows/update-helm-repo.yml | 29 - golang-external-secrets/Chart.yaml | 11 - golang-external-secrets/README.md | 18 - .../charts/external-secrets-0.10.0.tgz | Bin 82278 -> 0 bytes .../0001-runasuser-comment-out.patch | 48 - ...ternal-secrets-hub-clusterrolebinding.yaml | 23 - .../golang-external-secrets-hub-role.yaml | 22 - ...lang-external-secrets-hub-secretstore.yaml | 33 - ...lang-external-secrets-hub-secretstore.yaml | 43 - .../update-helm-dependency.sh | 29 - golang-external-secrets/values.yaml | 46 - .../.github/workflows/update-helm-repo.yml | 29 - hashicorp-vault/Chart.yaml | 10 - hashicorp-vault/README.md | 29 - hashicorp-vault/charts/vault-0.28.1.tgz | Bin 49807 -> 0 bytes .../0001-Allow-per-service-annotations.patch | 116 -- hashicorp-vault/templates/vault-app.yaml | 12 - hashicorp-vault/update-helm-dependency.sh | 29 - hashicorp-vault/values.yaml | 51 - .../.github/workflows/update-helm-repo.yml | 29 - letsencrypt/.helmignore | 23 - letsencrypt/Chart.yaml | 16 - letsencrypt/README.md | 72 -- letsencrypt/templates/api-cert.yaml | 28 - .../templates/cert-manager-installation.yaml | 38 - .../templates/credentials-request.yaml | 24 - letsencrypt/templates/default-routes.yaml | 46 - letsencrypt/templates/issuer.yaml | 25 - letsencrypt/templates/namespaces.yaml | 20 - letsencrypt/templates/wildcard-cert.yaml | 28 - letsencrypt/values.yaml | 60 - 82 files changed, 5679 deletions(-) delete mode 100644 acm/.github/workflows/update-helm-repo.yml delete mode 100644 acm/.helmignore delete mode 100644 acm/Chart.yaml delete mode 100644 acm/README.md delete mode 100644 acm/templates/_helpers.tpl delete mode 100644 acm/templates/multiclusterhub.yaml delete mode 100644 acm/templates/policies/acm-hub-ca-policy.yaml delete mode 100644 acm/templates/policies/application-policies.yaml delete mode 100644 acm/templates/policies/ocp-gitops-policy.yaml delete mode 100644 acm/templates/policies/private-repo-policies.yaml delete mode 100644 acm/templates/provision/_install-config.tpl delete mode 100644 acm/templates/provision/clusterdeployment.yaml delete mode 100644 acm/templates/provision/clusterpool.yaml delete mode 100644 acm/templates/provision/managedclusterset.yaml delete mode 100644 acm/templates/provision/secrets-aws.yaml delete mode 100644 acm/templates/provision/secrets-azure.yaml delete mode 100644 acm/templates/provision/secrets-common.yaml delete mode 100644 acm/test.yaml delete mode 100644 acm/values.yaml delete mode 100644 clustergroup/.github/workflows/update-helm-repo.yml delete mode 100644 clustergroup/.helmignore delete mode 100644 clustergroup/Chart.yaml delete mode 100644 clustergroup/README.md delete mode 100644 clustergroup/templates/_helpers.tpl delete mode 100644 clustergroup/templates/core/catalog-sources.yaml delete mode 100644 clustergroup/templates/core/namespaces.yaml delete mode 100644 clustergroup/templates/core/nodes.yaml delete mode 100644 clustergroup/templates/core/operatorgroup.yaml delete mode 100644 clustergroup/templates/core/scheduler.yaml delete mode 100644 clustergroup/templates/core/subscriptions.yaml delete mode 100644 clustergroup/templates/imperative/_helpers.tpl delete mode 100644 clustergroup/templates/imperative/auto-approve-installplans.yaml delete mode 100644 clustergroup/templates/imperative/clusterrole.yaml delete mode 100644 clustergroup/templates/imperative/configmap.yaml delete mode 100644 clustergroup/templates/imperative/job.yaml delete mode 100644 clustergroup/templates/imperative/namespace.yaml delete mode 100644 clustergroup/templates/imperative/rbac.yaml delete mode 100644 clustergroup/templates/imperative/role.yaml delete mode 100644 clustergroup/templates/imperative/serviceaccount.yaml delete mode 100644 clustergroup/templates/imperative/unsealjob.yaml delete mode 100644 clustergroup/templates/plumbing/applications.yaml delete mode 100644 clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml delete mode 100644 clustergroup/templates/plumbing/argocd-super-role.yaml delete mode 100644 clustergroup/templates/plumbing/argocd.yaml delete mode 100644 clustergroup/templates/plumbing/cluster-external-secrets.yaml delete mode 100644 clustergroup/templates/plumbing/gitops-namespace.yaml delete mode 100644 clustergroup/templates/plumbing/hosted-sites.yaml delete mode 100644 clustergroup/templates/plumbing/projects.yaml delete mode 100644 clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml delete mode 100644 clustergroup/values.schema.json delete mode 100644 clustergroup/values.yaml delete mode 100644 golang-external-secrets/.github/workflows/update-helm-repo.yml delete mode 100644 golang-external-secrets/Chart.yaml delete mode 100644 golang-external-secrets/README.md delete mode 100644 golang-external-secrets/charts/external-secrets-0.10.0.tgz delete mode 100644 golang-external-secrets/local-patches/0001-runasuser-comment-out.patch delete mode 100644 golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml delete mode 100644 golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-role.yaml delete mode 100644 golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-secretstore.yaml delete mode 100644 golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml delete mode 100755 golang-external-secrets/update-helm-dependency.sh delete mode 100644 golang-external-secrets/values.yaml delete mode 100644 hashicorp-vault/.github/workflows/update-helm-repo.yml delete mode 100644 hashicorp-vault/Chart.yaml delete mode 100644 hashicorp-vault/README.md delete mode 100644 hashicorp-vault/charts/vault-0.28.1.tgz delete mode 100644 hashicorp-vault/local-patches/0001-Allow-per-service-annotations.patch delete mode 100644 hashicorp-vault/templates/vault-app.yaml delete mode 100755 hashicorp-vault/update-helm-dependency.sh delete mode 100644 hashicorp-vault/values.yaml delete mode 100644 letsencrypt/.github/workflows/update-helm-repo.yml delete mode 100644 letsencrypt/.helmignore delete mode 100644 letsencrypt/Chart.yaml delete mode 100644 letsencrypt/README.md delete mode 100644 letsencrypt/templates/api-cert.yaml delete mode 100644 letsencrypt/templates/cert-manager-installation.yaml delete mode 100644 letsencrypt/templates/credentials-request.yaml delete mode 100644 letsencrypt/templates/default-routes.yaml delete mode 100644 letsencrypt/templates/issuer.yaml delete mode 100644 letsencrypt/templates/namespaces.yaml delete mode 100644 letsencrypt/templates/wildcard-cert.yaml delete mode 100644 letsencrypt/values.yaml diff --git a/acm/.github/workflows/update-helm-repo.yml b/acm/.github/workflows/update-helm-repo.yml deleted file mode 100644 index c12af2b5..00000000 --- a/acm/.github/workflows/update-helm-repo.yml +++ /dev/null @@ -1,29 +0,0 @@ -# This invokes the workflow named 'publish-charts' in the umbrella repo -# It expects to have a secret called CHARTS_REPOS_TOKEN which contains -# the GitHub token that has permissions to invoke workflows and commit code -# inside the umbrella-repo. -# The following fine-grained permissions were used in testing and were limited -# to the umbrella repo only: -# - Actions: r/w -# - Commit statuses: r/w -# - Contents: r/w -# - Deployments: r/w -# - Pages: r/w - -name: vp-patterns/update-helm-repo -on: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - -jobs: - helmlint: - uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: - contents: read - - update-helm-repo: - needs: [helmlint] - uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: read-all - secrets: inherit diff --git a/acm/.helmignore b/acm/.helmignore deleted file mode 100644 index b25c15b8..00000000 --- a/acm/.helmignore +++ /dev/null @@ -1 +0,0 @@ -*~ diff --git a/acm/Chart.yaml b/acm/Chart.yaml deleted file mode 100644 index adb30c66..00000000 --- a/acm/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -description: A Helm chart to configure Advanced Cluster Manager for OpenShift. -keywords: -- pattern -name: acm -version: 0.1.2 diff --git a/acm/README.md b/acm/README.md deleted file mode 100644 index 56b39ae3..00000000 --- a/acm/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Validated Patterns ACM chart - -This chart is used to set up ACM in [Validated Patterns](https://validatedpatterns.io) - -Please send PRs [here](https://github.com/validatedpatterns/common) diff --git a/acm/templates/_helpers.tpl b/acm/templates/_helpers.tpl deleted file mode 100644 index 1b934e62..00000000 --- a/acm/templates/_helpers.tpl +++ /dev/null @@ -1,59 +0,0 @@ -{{/* -Default always defined valueFiles to be included when pushing the cluster wide argo application via acm -*/}} -{{- define "acm.app.policies.valuefiles" -}} -- "/values-global.yaml" -- "/values-{{ .name }}.yaml" -- '/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}.yaml' -- '/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' -- '/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}-{{ .name }}.yaml' -# We cannot use $.Values.global.clusterVersion because that gets resolved to the -# hub's cluster version, whereas we want to include the spoke cluster version -- '/values-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' -{{- end }} {{- /*acm.app.policies.valuefiles */}} - -{{- define "acm.app.policies.multisourcevaluefiles" -}} -- "$patternref/values-global.yaml" -- "$patternref/values-{{ .name }}.yaml" -- '$patternref/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}.yaml' -- '$patternref/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' -- '$patternref/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}-{{ .name }}.yaml' -# We cannot use $.Values.global.clusterVersion because that gets resolved to the -# hub's cluster version, whereas we want to include the spoke cluster version -- '$patternref/values-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' -{{- end }} {{- /*acm.app.policies.multisourcevaluefiles */}} - -{{- define "acm.app.policies.helmparameters" -}} -- name: global.repoURL - value: {{ $.Values.global.repoURL }} -- name: global.originURL - value: {{ $.Values.global.originURL }} -- name: global.targetRevision - value: {{ $.Values.global.targetRevision }} -- name: global.namespace - value: $ARGOCD_APP_NAMESPACE -- name: global.pattern - value: {{ $.Values.global.pattern }} -- name: global.hubClusterDomain - value: {{ $.Values.global.hubClusterDomain }} -- name: global.localClusterDomain - value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}` }}' -- name: global.clusterDomain - value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}` }}' -- name: global.clusterVersion - value: '{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}' -- name: global.localClusterName - value: '{{ `{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}` }}' -- name: global.clusterPlatform - value: {{ $.Values.global.clusterPlatform }} -- name: global.multiSourceSupport - value: {{ $.Values.global.multiSourceSupport | quote }} -- name: global.multiSourceRepoUrl - value: {{ $.Values.global.multiSourceRepoUrl }} -- name: global.multiSourceTargetRevision - value: {{ $.Values.global.multiSourceTargetRevision }} -- name: global.privateRepo - value: {{ $.Values.global.privateRepo | quote }} -- name: global.experimentalCapabilities - value: {{ $.Values.global.experimentalCapabilities }} -{{- end }} {{- /*acm.app.policies.helmparameters */}} diff --git a/acm/templates/multiclusterhub.yaml b/acm/templates/multiclusterhub.yaml deleted file mode 100644 index a4e8b89b..00000000 --- a/acm/templates/multiclusterhub.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- $channel := "" }} -{{- if .Values.acm.mce_operator.channel }} -{{- $channel = printf ",\"channel\": \"%s\"" .Values.acm.mce_operator.channel }} -{{- end }} -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "{{ default "redhat-operators" .Values.acm.mce_operator.source }}" {{- $channel }} }' -spec: {} diff --git a/acm/templates/policies/acm-hub-ca-policy.yaml b/acm/templates/policies/acm-hub-ca-policy.yaml deleted file mode 100644 index 5759247c..00000000 --- a/acm/templates/policies/acm-hub-ca-policy.yaml +++ /dev/null @@ -1,226 +0,0 @@ -# This pushes out the HUB's Certificate Authorities on to the imported clusters -{{- if .Values.clusterGroup.isHubCluster }} -{{- if (eq (((.Values.global).secretStore).backend) "vault") }} ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-hub-ca-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-hub-ca-config-policy - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: hub-ca - namespace: golang-external-secrets - data: - hub-kube-root-ca.crt: '{{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}` }}' - hub-openshift-service-ca.crt: '{{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}` }}' - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: imperative - data: - hub-kube-root-ca.crt: | - {{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}}` }} - hub-openshift-service-ca.crt: | - {{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}}` }} ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-hub-ca-policy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-hub-ca-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-hub-ca-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-hub-ca-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-openshift-gitops-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: openshift-gitops - data: - hub-kube-root-ca.crt: | - {{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}}` }} - hub-openshift-service-ca.crt: | - {{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}}` }} ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-openshift-gitops-policy-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-openshift-gitops-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-openshift-gitops-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' - -{{- end }}{{/* if (eq (((.Values.global).secretStore).backend) "vault") */}} -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- $group := . }} -{{- if not .hostedArgoSites }} ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-{{ .name }}-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-{{ .name }}-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: {{ $.Values.global.pattern }}-{{ .name }} - data: - hub-kube-root-ca.crt: | - {{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}}` }} - hub-openshift-service-ca.crt: | - {{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}}` }} ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-{{ .name }}-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-{{ .name }}-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-{{ .name }}-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-{{ .name }}-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' -{{- end }}{{/* if not .hostedArgoSites */}} -{{- end }}{{/* range .Values.clusterGroup.managedClusterGroups */}} -{{- end }}{{/* isHubCluster */}} diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml deleted file mode 100644 index fd7c2a3f..00000000 --- a/acm/templates/policies/application-policies.yaml +++ /dev/null @@ -1,179 +0,0 @@ -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- $group := . }} -{{- if not .hostedArgoSites }} -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: {{ .name }}-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: {{ .name }}-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: {{ $.Values.global.pattern }}-{{ .name }} - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - {{- if $.Values.global.multiSourceSupport }} - sources: - - repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} - targetRevision: {{ coalesce .targetRevision $.Values.global.targetRevision }} - ref: patternref - - repoURL: {{ $.Values.global.multiSourceRepoUrl }} - targetRevision: {{ $.Values.global.multiSourceTargetRevision }} - chart: clustergroup - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - {{- range $k, $v := $.Values.extraParametersNested }} - {{ $k }}: {{ printf "%s" $v | quote }} - {{- end }} - valueFiles: - {{- include "acm.app.policies.multisourcevaluefiles" . | nindent 24 }} - {{- range $valueFile := .extraValueFiles }} - - {{ $valueFile | quote }} - {{- end }} - parameters: - {{- include "acm.app.policies.helmparameters" $ | nindent 24 }} - - name: clusterGroup.name - value: {{ $group.name }} - {{- range $k, $v := $.Values.extraParametersNested }} - - name: {{ $k }} - value: {{ printf "%s" $v | quote }} - {{- end }} - {{- range .helmOverrides }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end }} - {{- if .fileParameters }} - fileParameters: - {{- range .fileParameters }} - - name: {{ .name }} - path: {{ .path }} - {{- end }} - {{- end }} - - {{- else }} - source: - repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} - targetRevision: {{ coalesce .targetRevision $.Values.global.targetRevision }} - path: {{ default "common/clustergroup" .path }} - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - {{- range $k, $v := $.Values.extraParametersNested }} - {{ $k }}: {{ printf "%s" $v | quote }} - {{- end }} - valueFiles: - {{- include "acm.app.policies.valuefiles" . | nindent 22 }} - {{- range $valueFile := .extraValueFiles }} - - {{ $valueFile | quote }} - {{- end }} - parameters: - {{- include "acm.app.policies.helmparameters" $ | nindent 22 }} - - name: clusterGroup.name - value: {{ $group.name }} - {{- range $k, $v := $.Values.extraParametersNested }} - - name: {{ $k }} - value: {{ printf "%s" $v | quote }} - {{- end }} - {{- range .helmOverrides }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end }} - {{- if .fileParameters }} - fileParameters: - {{- range .fileParameters }} - - name: {{ .name }} - path: {{ .path }} - {{- end }} - {{- end }} - {{- end }}{{/* if $.Values.global.multiSourceSupport */}} - destination: - server: https://kubernetes.default.svc - namespace: {{ $.Values.global.pattern }}-{{ .name }} - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: {{ default 20 $.Values.global.options.applicationRetryLimit }} - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: {{ .name }}-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: {{ .name }}-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: {{ .name }}-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: {{ .name }}-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - {{- if .clusterSelector }} - clusterSelector: {{ .clusterSelector | toPrettyJson }} - {{- else if (not $group.acmlabels) }} - clusterSelector: - matchLabels: - clusterGroup: {{ $group.name }} - {{- else if eq (len $group.acmlabels) 0 }} - clusterSelector: - matchLabels: - clusterGroup: {{ $group.name }} - {{- else }} - clusterSelector: - matchLabels: - {{- range .acmlabels }} - {{ .name }}: {{ .value }} - {{- end }} - {{- end }} ---- -{{- end }} -{{- end }} diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml deleted file mode 100644 index 753e4447..00000000 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ /dev/null @@ -1,335 +0,0 @@ -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: {{ default "gitops-1.13" .Values.main.gitops.channel }} - installPlanApproval: Automatic - name: openshift-gitops-operator - source: {{ default "redhat-operators" .Values.main.gitops.operatorSource }} - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# This policy depends on openshift-gitops-policy and the reason is that we need to be -# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance -# because the initcontainer references the trusted-ca-bundle and if it starts without the -# configmap being there we risk running an argo instances that won't trust public CAs -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy-argocd - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - dependencies: - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: openshift-gitops-policy - namespace: open-cluster-management - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: hub-argo-ca-openshift-gitops-policy - namespace: open-cluster-management - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config-argocd - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1beta1 - kind: ArgoCD - metadata: - name: openshift-gitops - namespace: openshift-gitops - spec: - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - webhookServer: - ingress: - enabled: false - route: - enabled: false - controller: - processors: {} - resources: - limits: - cpu: "2" - memory: 2Gi - requests: - cpu: 250m - memory: 1Gi - sharding: {} - grafana: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - route: - enabled: false - ha: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - monitoring: - enabled: false - notifications: - enabled: false - prometheus: - enabled: false - ingress: - enabled: false - route: - enabled: false - rbac: - defaultPolicy: "" - policy: |- - g, system:cluster-admins, role:admin - g, cluster-admins, role:admin - scopes: '[groups]' - redis: - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt - || true - image: registry.redhat.io/ubi9/ubi-minimal:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - resourceExclusions: |- - - apiGroups: - - tekton.dev - clusters: - - '*' - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - {{- if and (.Values.global.argocdServer) (.Values.global.argocdServer.route) (.Values.global.argocdServer.route.tls) }} - tls: - insecureEdgeTerminationPolicy: {{ default "Redirect" .Values.global.argocdServer.route.tls.insecureEdgeTerminationPolicy }} - termination: {{ default "reencrypt" .Values.global.argocdServer.route.tls.termination }} - {{- end }} - service: - type: "" - sso: - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - provider: dex - tls: - ca: {} ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement-argocd - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy-argocd - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' diff --git a/acm/templates/policies/private-repo-policies.yaml b/acm/templates/policies/private-repo-policies.yaml deleted file mode 100644 index 0b7db0da..00000000 --- a/acm/templates/policies/private-repo-policies.yaml +++ /dev/null @@ -1,161 +0,0 @@ -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace -{{ if $.Values.global.privateRepo }} -{{ if .Values.clusterGroup.isHubCluster }} ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: private-hub-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: private-hub-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: vp-private-repo-credentials - namespace: open-cluster-management - labels: - argocd.argoproj.io/secret-type: repository - data: '{{ `{{copySecretData "openshift-gitops" "vp-private-repo-credentials"}}` }}' ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: private-hub-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: private-hub-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: private-hub-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: private-hub-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: In - values: - - 'true' ---- -{{ end }}{{- /* if .Values.clusterGroup.isHubCluster */}} -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- $group := . }} -{{- if not .hostedArgoSites }} -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: private-{{ .name }}-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: private-{{ .name }}-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: vp-private-repo-credentials - namespace: openshift-gitops - labels: - argocd.argoproj.io/secret-type: repository - data: '{{ `{{hub copySecretData "open-cluster-management" "vp-private-repo-credentials" hub}}` }}' - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: vp-private-repo-credentials - namespace: {{ $.Values.global.pattern }}-{{ .name }} - labels: - argocd.argoproj.io/secret-type: repository - data: '{{ `{{hub copySecretData "open-cluster-management" "vp-private-repo-credentials" hub}}` }}' ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: private-{{ .name }}-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: private-{{ .name }}-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: private-{{ .name }}-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: private-{{ .name }}-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' -{{- end }}{{- /* if not .hostedArgoSites */}} -{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} -{{- end }}{{- /* if $.Values.global.privateRepo */}} diff --git a/acm/templates/provision/_install-config.tpl b/acm/templates/provision/_install-config.tpl deleted file mode 100644 index b0336627..00000000 --- a/acm/templates/provision/_install-config.tpl +++ /dev/null @@ -1,66 +0,0 @@ -{{- define "cluster.install-config" -}} - -{{- $type := "None" }} -{{- $cloud := "None" }} -{{- $region := "None" }} - -{{- if .platform.aws }} -{{- $cloud = "aws" }} -{{- $region = .platform.aws.region }} -{{- $type = "m5.xlarge" }} -{{- else if .platform.azure }} -{{- $cloud = "azure" }} -{{- $region = .platform.azure.region }} -{{- $type = "Standard_D8s_v3" }} -{{- end }} - -apiVersion: v1 -metadata: - name: '{{ .name }}' -baseDomain: {{ .baseDomain }} -controlPlane: - architecture: amd64 - hyperthreading: Enabled - name: controlPlane - {{- if .controlPlane }} - replicas: {{ default 3 .controlPlane.count }} - {{- if .controlPlane.platform }} - platform: - {{- toYaml .controlPlane.platform | nindent 4 }} - {{- end }} - {{- else }} - replicas: 3 - platform: - {{ $cloud }}: - type: {{ $type }} - {{- end }} -compute: -- hyperthreading: Enabled - architecture: amd64 - name: 'worker' - {{- if .workers }} - replicas: {{ default 0 .workers.count }} - {{- if .workers.platform }} - platform: - {{- toYaml .workers.platform | nindent 4 }} - {{- end }} - {{- else }} - replicas: 3 - platform: - {{ $cloud }}: - type: {{ $type }} - {{- end }} -networking: - clusterNetwork: - - cidr: 10.128.0.0/14 - hostPrefix: 23 - machineNetwork: - - cidr: 10.0.0.0/16 - networkType: OVNKubernetes - serviceNetwork: - - 172.30.0.0/16 -platform: -{{- toYaml .platform | nindent 2 }} -pullSecret: "" # skip, hive will inject based on it's secrets -sshKey: "" # skip, hive will inject based on it's secrets -{{- end -}} diff --git a/acm/templates/provision/clusterdeployment.yaml b/acm/templates/provision/clusterdeployment.yaml deleted file mode 100644 index f7f71a52..00000000 --- a/acm/templates/provision/clusterdeployment.yaml +++ /dev/null @@ -1,83 +0,0 @@ -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- $group := . }} - -{{- range $group.clusterDeployments}} -{{ $cluster := . }} - -{{- if (eq $cluster.name nil) }} -{{- fail (printf "managedClusterGroup clusterDeployment cluster name is empty: %s" $cluster) }} -{{- end }} -{{- if (eq $group.name nil) }} -{{- fail (printf "managedClusterGroup clusterDeployment group name is empty: %s" $cluster) }} -{{- end }} - -{{- $deploymentName := print $cluster.name "-" $group.name }} - -{{- $cloud := "None" }} -{{- $region := "None" }} - -{{- if $cluster.platform.aws }} -{{- $cloud = "aws" }} -{{- $region = $cluster.platform.aws.region }} -{{- else if $cluster.platform.azure }} -{{- $cloud = "azure" }} -{{- $region = $cluster.platform.azure.region }} -{{- end }} - ---- -apiVersion: v1 -kind: Namespace -metadata: - name: {{ $deploymentName }} - ---- -apiVersion: hive.openshift.io/v1 -kind: ClusterDeployment -metadata: - name: {{ $deploymentName }} - namespace: {{ $deploymentName }} - labels: - vendor: OpenShift - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - baseDomain: {{ $cluster.baseDomain }} - clusterName: {{ $deploymentName }} - installAttemptsLimit: 1 - platform: - {{ $cloud }}: - credentialsSecretRef: - name: {{ $deploymentName }}-creds - region: {{ $region }} - provisioning: - installConfigSecretRef: - name: {{ $deploymentName }}-install-config - sshPrivateKeySecretRef: - name: {{ $deploymentName }}-ssh-private-key - imageSetRef: - name: img{{ $cluster.openshiftVersion }}-multi-appsub - pullSecretRef: - name: {{ $deploymentName }}-pull-secret - ---- -apiVersion: cluster.open-cluster-management.io/v1 -kind: ManagedCluster -metadata: - labels: - cluster.open-cluster-management.io/clusterset: {{ $group.name }} - {{- if (not $group.acmlabels) }} - clusterGroup: {{ $group.name }} - {{- else if eq (len $group.acmlabels) 0 }} - clusterGroup: {{ $group.name }} - {{- else }} - {{- range $group.acmlabels }} - {{ .name }}: {{ .value }} - {{- end }} - {{- end }} - name: {{ $deploymentName }} - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - hubAcceptsClient: true -{{- end }}{{- /* range $group.clusterDeployments */}} -{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/acm/templates/provision/clusterpool.yaml b/acm/templates/provision/clusterpool.yaml deleted file mode 100644 index dab4dd28..00000000 --- a/acm/templates/provision/clusterpool.yaml +++ /dev/null @@ -1,82 +0,0 @@ -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- $group := . }} -{{- range .clusterPools }} - -{{- $pool := . }} -{{- $poolName := print .name "-" $group.name }} - -{{- $cloud := "None" }} -{{- $region := "None" }} -{{- $numClusters := 0 }} - -{{- if .platform.aws }} -{{- $cloud = "aws" }} -{{- $region = .platform.aws.region }} -{{- else if .platform.azure }} -{{- $cloud = "azure" }} -{{- $region = .platform.azure.region }} -{{- end }} - -{{- if .clusters }} -{{- $numClusters = len .clusters }} -{{- end }} - -apiVersion: hive.openshift.io/v1 -kind: ClusterPool -metadata: - name: "{{ $poolName }}" - annotations: - argocd.argoproj.io/sync-wave: "10" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - labels: - cloud: {{ $cloud }} - region: '{{ $region }}' - vendor: OpenShift - cluster.open-cluster-management.io/clusterset: {{ $group.name }} -spec: - {{- if .size }} - size: {{ .size }} - {{- else }} - size: {{ $numClusters }} - {{- end }} - runningCount: {{ $numClusters }} - baseDomain: {{ .baseDomain }} - installConfigSecretTemplateRef: - name: {{ $poolName }}-install-config - imageSetRef: - name: img{{ .openshiftVersion }}-multi-appsub - pullSecretRef: - name: {{ $poolName }}-pull-secret - skipMachinePools: true # Disable MachinePool as using custom install-config - platform: - {{ $cloud }}: - credentialsSecretRef: - name: {{ $poolName }}-creds - region: {{ $region }} ---- -{{- range .clusters }} -apiVersion: hive.openshift.io/v1 -kind: ClusterClaim -metadata: - name: '{{ lower . }}-{{ lower $group.name }}' - annotations: - argocd.argoproj.io/sync-wave: "20" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - cluster.open-cluster-management.io/createmanagedcluster: "true" - labels: - clusterClaimName: {{ lower . }}-{{ lower $group.name }} - {{- if (not $group.acmlabels) }} - clusterGroup: {{ $group.name }} - {{- else if eq (len $group.acmlabels) 0 }} - clusterGroup: {{ $group.name }} - {{- else }} - {{- range $group.acmlabels }} - {{ .name }}: {{ .value }} - {{- end }} - {{- end }} -spec: - clusterPoolName: {{ $poolName }} ---- -{{- end }}{{- /* range .range clusters */}} -{{- end }}{{- /* range .clusterPools */}} -{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/acm/templates/provision/managedclusterset.yaml b/acm/templates/provision/managedclusterset.yaml deleted file mode 100644 index 2c8eaffa..00000000 --- a/acm/templates/provision/managedclusterset.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- if or .clusterPools .clusterDeployments }}{{- /* We only create ManagedClusterSets if there are clusterPools or clusterDeployments defined */}} ---- -apiVersion: cluster.open-cluster-management.io/v1beta2 -kind: ManagedClusterSet -metadata: - annotations: - cluster.open-cluster-management.io/submariner-broker-ns: {{ .name }}-broker - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - name: {{ .name }} - -{{- end }}{{- /* if .clusterPools) */}} -{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/acm/templates/provision/secrets-aws.yaml b/acm/templates/provision/secrets-aws.yaml deleted file mode 100644 index 911aff4a..00000000 --- a/acm/templates/provision/secrets-aws.yaml +++ /dev/null @@ -1,111 +0,0 @@ -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- $group := . }} -{{- range .clusterPools }} -{{- $poolName := print .name "-" $group.name }} -{{- if .platform.aws }} ---- -{{- template "externalsecret.aws.creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} ---- -{{- template "externalsecret.aws.infra-creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} - -{{- end }}{{- /* if .platform.aws */}} -{{- end }}{{- /* range .clusterPools */}} - -{{- range .clusterDeployments }} -{{- $deploymentName := print .name "-" $group.name }} -{{- if .platform.aws }} ---- -{{- template "externalsecret.aws.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} ---- -{{- template "externalsecret.aws.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} - -{{- end }}{{- /* if .platform.aws */}} -{{- end }}{{- /* range .clusterDeployments */}} - -{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} - -{{- define "externalsecret.aws.creds" }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ .name }}-creds - {{- if .namespaced }} - namespace: {{ .name }} - {{- end }} -spec: - dataFrom: - - extract: - # Expects entries called: aws_access_key_id and aws_secret_access_key - key: {{ default "secret/data/hub/aws" .context.awsKeyPath }} - refreshInterval: 24h0m0s - secretStoreRef: - name: {{ .secretStore.name }} - kind: {{ .secretStore.kind }} - target: - name: {{ .name }}-creds - creationPolicy: Owner - template: - type: Opaque -{{- end}} - -{{- define "externalsecret.aws.infra-creds"}} -# For use when manually creating clusters with ACM -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ .name }}-infra-creds - {{- if .namespaced }} - namespace: {{ .name }} - {{- end }} -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: {{ default "secret/data/hub/openshiftPullSecret" .context.pullSecretKeyPath }} - property: content - - secretKey: awsKeyId - remoteRef: - key: {{ default "secret/data/hub/aws" .context.awsKeyPath }} - property: aws_access_key_id - - secretKey: awsAccessKey - remoteRef: - key: {{ default "secret/data/hub/aws" .context.awsKeyPath }} - property: aws_secret_access_key - - secretKey: sshPublicKey - remoteRef: - key: {{ default "secret/data/hub/publickey" .context.sshPublicKeyPath }} - property: content - - secretKey: sshPrivateKey - remoteRef: - key: {{ default "secret/data/hub/privatekey" .context.sshPrivateKeyPath }} - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: {{ .secretStore.name }} - kind: {{ .secretStore.kind }} - target: - name: {{ .name }}-infra-creds - creationPolicy: Owner - template: - type: Opaque - metadata: - labels: - cluster.open-cluster-management.io/credentials: "" - cluster.open-cluster-management.io/type: aws - data: - baseDomain: "{{ .context.baseDomain }}" - pullSecret: |- - {{ "{{ .openshiftPullSecret | toString }}" }} - aws_access_key_id: |- - {{ "{{ .awsKeyId | toString }}" }} - aws_secret_access_key: |- - {{ "{{ .awsAccessKey | toString }}" }} - ssh-privatekey: |- - {{ "{{ .sshPrivateKey | toString }}" }} - ssh-publickey: |- - {{ "{{ .sshPublicKey | toString }}" }} - httpProxy: "" - httpsProxy: "" - noProxy: "" - additionalTrustBundle: "" -{{- end}} diff --git a/acm/templates/provision/secrets-azure.yaml b/acm/templates/provision/secrets-azure.yaml deleted file mode 100644 index 1ef5842c..00000000 --- a/acm/templates/provision/secrets-azure.yaml +++ /dev/null @@ -1,113 +0,0 @@ -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- $group := . }} -{{- range .clusterPools }} -{{- $poolName := print .name "-" $group.name }} -{{- if .platform.azure }} ---- -{{- template "externalsecret.azure.creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} ---- -{{- template "externalsecret.azure.infra-creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} - ---- -{{- end }}{{- /* if .platform.azure */}} -{{- end }}{{- /* range .clusterPools */}} - -{{- range .clusterDeployments }} -{{- $deploymentName := print .name "-" $group.name }} -{{- if .platform.azure }} ---- -{{- template "externalsecret.azure.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} ---- -{{- template "externalsecret.azure.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} - - -{{- end }}{{- /* if .platform.azure */}} -{{- end }}{{- /* range .clusterPools */}} - -{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} - -{{- define "externalsecret.azure.creds" }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ .name }}-creds - {{- if .namespaced }} - namespace: {{ .name }} - {{- end }} -spec: - data: - - secretKey: azureOsServicePrincipal - remoteRef: - key: {{ default "secret/data/hub/azureOsServicePrincipal" .context.azureKeyPath }} - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: {{ .secretStore.name }} - kind: {{ .secretStore.kind }} - target: - name: {{ .name }}-creds - creationPolicy: Owner - template: - type: Opaque - data: - osServicePrincipal.json: |- - {{ "{{ .azureOsServicePrincipal | toString }}" }} -{{- end }} - -{{- define "externalsecret.azure.infra-creds"}} -# For use when manually creating clusters with ACM -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ .name }}-infra-creds - {{- if .namespaced }} - namespace: {{ .name }} - {{- end }} -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: {{ default "secret/data/hub/openshiftPullSecret" .context.pullSecretKeyPath }} - property: content - - secretKey: sshPublicKey - remoteRef: - key: {{ default "secret/data/hub/publickey" .context.sshPublicKeyPath }} - property: content - - secretKey: sshPrivateKey - remoteRef: - key: {{ default "secret/data/hub/privatekey" .context.sshPrivateKeyPath }} - property: content - - secretKey: azureOsServicePrincipal - remoteRef: - key: {{ default "secret/data/hub/azureOsServicePrincipal" .context.azureKeyPath }} - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: {{ .secretStore.name }} - kind: {{ .secretStore.kind }} - target: - name: {{ .name }}-infra-creds - creationPolicy: Owner - template: - type: Opaque - metadata: - labels: - cluster.open-cluster-management.io/credentials: "" - cluster.open-cluster-management.io/type: aws - data: - cloudName: AzurePublicCloud - osServicePrincipal.json: |- - {{ "{{ .azureOsServicePrincipal | toString }}" }} - baseDomain: "{{ .context.baseDomain }}" - baseDomainResourceGroupName: "{{ .context.platform.azure.baseDomainResourceGroupName | toString }}" - pullSecret: |- - {{ "{{ .openshiftPullSecret | toString }}" }} - ssh-privatekey: |- - {{ "{{ .sshPrivateKey | toString }}" }} - ssh-publickey: |- - {{ "{{ .sshPublicKey | toString }}" }} - httpProxy: "" - httpsProxy: "" - noProxy: "" - additionalTrustBundle: "" -{{- end }} diff --git a/acm/templates/provision/secrets-common.yaml b/acm/templates/provision/secrets-common.yaml deleted file mode 100644 index 6901c79c..00000000 --- a/acm/templates/provision/secrets-common.yaml +++ /dev/null @@ -1,95 +0,0 @@ -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- $group := . }} - -{{- range .clusterPools }} -{{- $poolName := print .name "-" $group.name }} ---- -{{- template "secret.install-config" (dict "name" $poolName "context" .) }} ---- -{{- template "externalsecret.pull-secret" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} ---- -{{- template "externalsecret.ssh.private.key" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} -{{- end }}{{- /* range .clusterPools */}} - -{{- range .clusterDeployments }} -{{- $deploymentName := print .name "-" $group.name }} ---- -{{- template "secret.install-config" (dict "name" $deploymentName "context" . "namespaced" true) }} ---- -{{- template "externalsecret.pull-secret" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} ---- -{{- template "externalsecret.ssh.private.key" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} -{{- end }}{{- /* range .clusterDeplyments */}} - -{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} - -{{- define "secret.install-config"}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ .name }}-install-config - {{- if .namespaced }} - namespace: {{ .name }} - {{- end }} -data: - # Base64 encoding of install-config yaml - install-config.yaml: {{ include "cluster.install-config" .context | b64enc }} -type: Opaque -{{- end }} - -{{- define "externalsecret.pull-secret" }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ .name }}-pull-secret - {{- if .namespaced }} - namespace: {{ .name }} - {{- end }} -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: {{ default "secret/data/hub/openshiftPullSecret" .context.pullSecretKeyPath }} - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: {{ .secretStore.name }} - kind: {{ .secretStore.kind }} - target: - name: {{ .name }}-pull-secret - creationPolicy: Owner - template: - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: |- - {{ "{{ .openshiftPullSecret | toString }}" }} -{{- end }} - - -{{- define "externalsecret.ssh.private.key" }} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ .name }}-ssh-private-key - {{- if .namespaced }} - namespace: {{ .name }} - {{- end }} -spec: - data: - - secretKey: sshPrivateKey - remoteRef: - key: {{ default "secret/data/hub/privatekey" .context.sshPrivateKeyPath }} - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: {{ .secretStore.name }} - kind: {{ .secretStore.kind }} - target: - name: {{ .name }}-ssh-private-key - creationPolicy: Owner - template: - type: Opaque - data: - ssh-privatekey: |- - {{ "{{ .sshPrivateKey | toString }}" }} -{{- end }} diff --git a/acm/test.yaml b/acm/test.yaml deleted file mode 100644 index 669daf07..00000000 --- a/acm/test.yaml +++ /dev/null @@ -1,35 +0,0 @@ -clusterGroup: - managedClusterGroups: - exampleRegion: - name: region-one - - # Before enabling cluster provisioning, ensure AWS/Azure credentials and OCP - # pull secrets are defined in Vault. See values-secret.yaml.template - # - clusterPools: - exampleAWSPool: - name: aws-ap - openshiftVersion: 4.10.18 - baseDomain: blueprints.rhecoeng.com - platform: - aws: - region: ap-southeast-2 - clusters: - - One - exampleAzurePool: - name: azure-us - openshiftVersion: 4.10.18 - baseDomain: blueprints.rhecoeng.com - platform: - azure: - baseDomainResourceGroupName: dojo-dns-zones - region: eastus - clusters: - - Two - - Three - acmlabels: - - name: clusterGroup - value: region-one - helmOverrides: - - name: clusterGroup.isHubCluster - value: false diff --git a/acm/values.yaml b/acm/values.yaml deleted file mode 100644 index ff5777da..00000000 --- a/acm/values.yaml +++ /dev/null @@ -1,61 +0,0 @@ -main: - gitops: - channel: "gitops-1.13" - -global: - extraValueFiles: [] - pattern: none - repoURL: none - targetRevision: main - options: - applicationRetryLimit: 20 - secretStore: - backend: "vault" - -clusterGroup: - subscriptions: - acm: - source: redhat-operators - managedClusterGroups: -# testRegion: -# name: region-one -# clusterPools: -# testPool: -# name: spoke -# openshiftVersion: 4.10.18 -# baseDomain: blueprints.rhecoeng.com -# platform: -# aws: -# region: ap-southeast-2 -# clusters: -# - spoke1 -# labels: -# - name: clusterGroup -# value: region-one -# testRegionTwo: -# name: region-two -# clusterDeployments: -# myFirstCluster: -# name: mcluster1 -# openshiftVersion: 4.10.18 -# baseDomain: blueprints.rhecoeng.com -# platform: -# azure: -# baseDomainResourceGroupName: dojo-dns-zones -# region: eastus -# labels: -# - name: clusterGroup -# value: region-two - -acm: - # Just used for IIB testing, drives the source and channel for the MCE - # subscription triggered by ACM - mce_operator: - source: redhat-operators - channel: null - - - -secretStore: - name: vault-backend - kind: ClusterSecretStore diff --git a/clustergroup/.github/workflows/update-helm-repo.yml b/clustergroup/.github/workflows/update-helm-repo.yml deleted file mode 100644 index fa1d6247..00000000 --- a/clustergroup/.github/workflows/update-helm-repo.yml +++ /dev/null @@ -1,30 +0,0 @@ -# This invokes the workflow named 'publish-charts' in the umbrella repo -# It expects to have a secret called CHARTS_REPOS_TOKEN which contains -# the GitHub token that has permissions to invoke workflows and commit code -# inside the umbrella-repo. -# The following fine-grained permissions were used in testing and were limited -# to the umbrella repo only: -# - Actions: r/w -# - Commit statuses: r/w -# - Contents: r/w -# - Deployments: r/w -# - Pages: r/w -# - -name: vp-patterns/update-helm-repo -on: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - -jobs: - helmlint: - uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: - contents: read - - update-helm-repo: - needs: [helmlint] - uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: read-all - secrets: inherit diff --git a/clustergroup/.helmignore b/clustergroup/.helmignore deleted file mode 100644 index b25c15b8..00000000 --- a/clustergroup/.helmignore +++ /dev/null @@ -1 +0,0 @@ -*~ diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml deleted file mode 100644 index 23764f5e..00000000 --- a/clustergroup/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -description: A Helm chart to create per-clustergroup ArgoCD applications and any required namespaces or subscriptions. -keywords: -- pattern -name: clustergroup -version: 0.8.14 diff --git a/clustergroup/README.md b/clustergroup/README.md deleted file mode 100644 index bb522d12..00000000 --- a/clustergroup/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Validated Patterns ClusterGroup chart - -This chart is used to set up the basic building blocks in [Validated Patterns](https://validatedpatterns.io) - -Please send PRs [here](https://github.com/validatedpatterns/common) diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl deleted file mode 100644 index 317ed4b1..00000000 --- a/clustergroup/templates/_helpers.tpl +++ /dev/null @@ -1,242 +0,0 @@ -{{/* -Default always defined top-level variables for helm charts -*/}} -{{- define "clustergroup.app.globalvalues.helmparameters" -}} -- name: global.repoURL - value: {{ $.Values.global.repoURL }} -- name: global.originURL - value: {{ $.Values.global.originURL }} -- name: global.targetRevision - value: {{ $.Values.global.targetRevision }} -- name: global.namespace - value: $ARGOCD_APP_NAMESPACE -- name: global.pattern - value: {{ $.Values.global.pattern }} -- name: global.clusterDomain - value: {{ $.Values.global.clusterDomain }} -- name: global.clusterVersion - value: "{{ $.Values.global.clusterVersion }}" -- name: global.clusterPlatform - value: "{{ $.Values.global.clusterPlatform }}" -- name: global.hubClusterDomain - value: {{ $.Values.global.hubClusterDomain }} -- name: global.multiSourceSupport - value: {{ $.Values.global.multiSourceSupport | quote }} -- name: global.multiSourceRepoUrl - value: {{ $.Values.global.multiSourceRepoUrl }} -- name: global.multiSourceTargetRevision - value: {{ $.Values.global.multiSourceTargetRevision }} -- name: global.localClusterDomain - value: {{ coalesce $.Values.global.localClusterDomain $.Values.global.hubClusterDomain }} -- name: global.privateRepo - value: {{ $.Values.global.privateRepo | quote }} -- name: global.experimentalCapabilities - value: {{ $.Values.global.experimentalCapabilities | default "" }} -{{- end }} {{/* clustergroup.globalvaluesparameters */}} - - -{{/* -Default always defined valueFiles to be included in Applications -*/}} -{{- define "clustergroup.app.globalvalues.valuefiles" -}} -- "/values-global.yaml" -- "/values-{{ $.Values.clusterGroup.name }}.yaml" -{{- if $.Values.global.clusterPlatform }} -- "/values-{{ $.Values.global.clusterPlatform }}.yaml" - {{- if $.Values.global.clusterVersion }} -- "/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.global.clusterVersion }}.yaml" - {{- end }} -- "/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.clusterGroup.name }}.yaml" -{{- end }} -{{- if $.Values.global.clusterVersion }} -- "/values-{{ $.Values.global.clusterVersion }}-{{ $.Values.clusterGroup.name }}.yaml" -{{- end }} -{{- if $.Values.global.extraValueFiles }} -{{- range $.Values.global.extraValueFiles }} -- {{ . | quote }} -{{- end }} {{/* range $.Values.global.extraValueFiles */}} -{{- end }} {{/* if $.Values.global.extraValueFiles */}} -{{- end }} {{/* clustergroup.app.globalvalues.valuefiles */}} - -{{/* -Default always defined valueFiles to be included in Applications but with a prefix called $patternref -*/}} -{{- define "clustergroup.app.globalvalues.prefixedvaluefiles" -}} -- "$patternref/values-global.yaml" -- "$patternref/values-{{ $.Values.clusterGroup.name }}.yaml" -{{- if $.Values.global.clusterPlatform }} -- "$patternref/values-{{ $.Values.global.clusterPlatform }}.yaml" - {{- if $.Values.global.clusterVersion }} -- "$patternref/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.global.clusterVersion }}.yaml" - {{- end }} -- "$patternref/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.clusterGroup.name }}.yaml" -{{- end }} -{{- if $.Values.global.clusterVersion }} -- "$patternref/values-{{ $.Values.global.clusterVersion }}-{{ $.Values.clusterGroup.name }}.yaml" -{{- end }} -{{- if $.Values.global.extraValueFiles }} -{{- range $.Values.global.extraValueFiles }} -- "$patternref/{{ . }}" -{{- end }} {{/* range $.Values.global.extraValueFiles */}} -{{- end }} {{/* if $.Values.global.extraValueFiles */}} -{{- end }} {{/* clustergroup.app.globalvalues.prefixedvaluefiles */}} - -{{/* -Helper function to generate AppProject from a map object -Called from common/clustergroup/templates/plumbing/projects.yaml -*/}} -{{- define "clustergroup.template.plumbing.projects.map" -}} -{{- $projects := index . 0 }} -{{- $namespace := index . 1 }} -{{- $enabled := index . 2 }} -{{- range $k, $v := $projects}} -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: {{ $k }} -{{- if (eq $enabled "plumbing") }} - namespace: openshift-gitops -{{- else }} - namespace: {{ $namespace }} -{{- end }} -spec: - description: "Pattern {{ . }}" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -{{- end }} -{{- end }} - -{{/* - Helper function to generate AppProject from a list object. - Called from common/clustergroup/templates/plumbing/projects.yaml -*/}} -{{- define "clustergroup.template.plumbing.projects.list" -}} -{{- $projects := index . 0 }} -{{- $namespace := index . 1 }} -{{- $enabled := index . 2 }} -{{- range $projects}} -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: {{ . }} -{{- if (eq $enabled "plumbing") }} - namespace: openshift-gitops -{{- else }} - namespace: {{ $namespace }} -{{- end }} -spec: - description: "Pattern {{ . }}" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} -{{- end }} -{{- end }} - -{{/* - Helper function to generate Namespaces from a map object. - Arguments passed as a list object are: - 0 - The namespace hash keys - 1 - Pattern name from .Values.global.pattern - 2 - Cluster group name from .Values.clusterGroup.name - Called from common/clustergroup/templates/core/namespaces.yaml -*/}} -{{- define "clustergroup.template.core.namespaces.map" -}} -{{- $ns := index . 0 }} -{{- $patternName := index . 1 }} -{{- $clusterGroupName := index . 2 }} - -{{- range $k, $v := $ns }}{{- /* We loop here even though the map has always just one key */}} -apiVersion: v1 -kind: Namespace -metadata: - name: {{ $k }} - {{- if ne $v nil }} - labels: - argocd.argoproj.io/managed-by: {{ $patternName }}-{{ $clusterGroupName }} - {{- if $v.labels }} - {{- range $key, $value := $v.labels }} {{- /* We loop here even though the map has always just one key */}} - {{ $key }}: {{ $value | default "" | quote }} - {{- end }} - {{- end }} - {{- if $v.annotations }} - annotations: - {{- range $key, $value := $v.annotations }} {{- /* We loop through the map to get key/value pairs */}} - {{ $key }}: {{ $value | default "" | quote }} - {{- end }} - {{- end }}{{- /* if $v.annotations */}} - {{- end }} -spec: ---- -{{- end }}{{- /* range $k, $v := $ns */}} -{{- end }} - -{{- /* - Helper function to generate OperatorGroup from a map object. - Arguments passed as a list object are: - 0 - The namespace hash keys - 1 - The operatorExcludes section from .Values.clusterGroup.operatorgroupExcludes - Called from common/clustergroup/templates/core/operatorgroup.yaml -*/ -}} -{{- define "clustergroup.template.core.operatorgroup.map" -}} -{{- $ns := index . 0 }} -{{- $operatorgroupExcludes := index . 1 }} -{{- if or (empty $operatorgroupExcludes) (not (has . $operatorgroupExcludes)) }} - {{- range $k, $v := $ns }}{{- /* We loop here even though the map has always just one key */}} - {{- if $v }} - {{- if or $v.operatorGroup (not (hasKey $v "operatorGroup")) }}{{- /* Checks if the user sets operatorGroup: false */}} ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: {{ $k }}-operator-group - namespace: {{ $k }} - {{- if (hasKey $v "targetNamespaces") }} - {{- if $v.targetNamespaces }} - {{- if (len $v.targetNamespaces) }} -spec: - targetNamespaces: - {{- range $v.targetNamespaces }}{{- /* We loop through the list of tergetnamespaces */}} - - {{ . }} - {{- end }}{{- /* End range targetNamespaces */}} - {{- end }}{{- /* End if (len $v.targetNamespaces) */}} - {{- end }}{{- /* End $v.targetNamespaces */}} - {{- else }} -spec: - targetNamespaces: - - {{ $k }} - {{- end }}{{- /* End of if hasKey $v "targetNamespaces" */}} - {{- end }}{{- /* End if $v.operatorGroup */}} - {{- else }}{{- /* else if $v == nil */}} ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: {{ $k }}-operator-group - namespace: {{ $k }} -spec: - targetNamespaces: - - {{ $k }} - {{- end }}{{- /* end if $v */}} - {{- end }}{{- /* End range $k, $v = $ns */}} -{{- end }}{{- /* End of if operatorGroupExcludes */}} -{{- end }} {{- /* End define "clustergroup.template.core.operatorgroup.map" */}} diff --git a/clustergroup/templates/core/catalog-sources.yaml b/clustergroup/templates/core/catalog-sources.yaml deleted file mode 100644 index 73c2e949..00000000 --- a/clustergroup/templates/core/catalog-sources.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{- range .Values.clusterGroup.indexImages }} -{{- $name := mustRegexReplaceAll "[^/]*/(.*):.*" .image "${1}" | replace "/" "-" }} -apiVersion: operators.coreos.com/v1alpha1 -kind: CatalogSource -metadata: - name: {{ coalesce .name $name }} - namespace: openshift-marketplace -spec: - sourceType: grpc - image: {{ .image }} ---- -{{- end -}} -{{- end -}} diff --git a/clustergroup/templates/core/namespaces.yaml b/clustergroup/templates/core/namespaces.yaml deleted file mode 100644 index c9a26afb..00000000 --- a/clustergroup/templates/core/namespaces.yaml +++ /dev/null @@ -1,42 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{- /* - We first check if namespaces are defined as a map. If it is we call - our helper function in _helpers.tpl to process the namespaces - described in the values file. This is to support issue - https://github.com/validatedpatterns/common/issues/459 created by our customer. -*/ -}} -{{- if kindIs "map" .Values.clusterGroup.namespaces }} -{{- template "clustergroup.template.core.namespaces.map" (list .Values.clusterGroup.namespaces $.Values.global.pattern $.Values.clusterGroup.name) }} -{{- else }} -{{- range $ns := .Values.clusterGroup.namespaces }} -apiVersion: v1 -kind: Namespace -metadata: - {{- if kindIs "map" $ns }} - {{- range $k, $v := $ns }}{{- /* We loop here even though the map has always just one key */}} - name: {{ $k }} - labels: - argocd.argoproj.io/managed-by: {{ $.Values.global.pattern }}-{{ $.Values.clusterGroup.name }} - {{- if $v.labels }} - {{- range $key, $value := $v.labels }} {{- /* We loop here even though the map has always just one key */}} - {{ $key }}: {{ $value | default "" | quote }} - {{- end }} - {{- end }} - {{- if $v.annotations }} - annotations: - {{- range $key, $value := $v.annotations }} {{- /* We loop through the map to get key/value pairs */}} - {{ $key }}: {{ $value | default "" | quote }} - {{- end }} - {{- end }}{{- /* if $v.annotations */}} - {{- end }}{{- /* range $k, $v := $ns */}} - - {{- else if kindIs "string" $ns }} - labels: - argocd.argoproj.io/managed-by: {{ $.Values.global.pattern }}-{{ $.Values.clusterGroup.name }} - name: {{ $ns }} - {{- end }} {{- /* if kindIs "string" $ns */}} -spec: ---- -{{- end }} -{{- end }} -{{- end }} diff --git a/clustergroup/templates/core/nodes.yaml b/clustergroup/templates/core/nodes.yaml deleted file mode 100644 index 5106447d..00000000 --- a/clustergroup/templates/core/nodes.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{- range $node := .Values.clusterGroup.nodes }} -apiVersion: v1 -kind: Node -metadata: - {{- range $k, $v := $node }} - name: {{ $k }} - labels: - argocd.argoproj.io/managed-by: {{ $.Values.global.pattern }}-{{ $.Values.clusterGroup.name }} - {{- if $v.labels }} - {{- range $key, $value := $v.labels }} - {{ $key }}: {{ $value | default "" | quote }} - {{- end }} - {{- end }} - - {{- if $v.annotations }} - annotations: - {{- range $key, $value := $v.annotations }} - {{ $key }}: {{ $value | default "" | quote }} - {{- end }} - {{- end }}{{- /* if $v.annotations */}} - {{- end }}{{- /* range $k, $v := $node */}} ---- -{{- end -}} -{{- end -}} diff --git a/clustergroup/templates/core/operatorgroup.yaml b/clustergroup/templates/core/operatorgroup.yaml deleted file mode 100644 index 6adfef47..00000000 --- a/clustergroup/templates/core/operatorgroup.yaml +++ /dev/null @@ -1,54 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{- /* - We first check if namespaces are defined as a map. If it is we call - our helper function in _helpers.tpl to process the projects - described in the values file. This is to support issue - https://github.com/validatedpatterns/common/issues/459 created by our customer. -*/ -}} -{{- if kindIs "map" .Values.clusterGroup.namespaces }} -{{- template "clustergroup.template.core.operatorgroup.map" (list .Values.clusterGroup.namespaces .Values.clusterGroup.operatorgroupExcludes) }} -{{- else }} -{{- range $ns := .Values.clusterGroup.namespaces }} - -{{- if or (empty $.Values.clusterGroup.operatorgroupExcludes) (not (has . $.Values.clusterGroup.operatorgroupExcludes)) }} - - {{- if kindIs "map" $ns }} - {{- range $k, $v := $ns }}{{- /* We loop here even though the map has always just one key */}} - {{- if $v.operatorGroup }}{{- /* Checks if the user sets operatorGroup: false */}} ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: {{ $k }}-operator-group - namespace: {{ $k }} - {{- if (hasKey $v "targetNamespaces") }} - {{- if $v.targetNamespaces }} -spec: - targetNamespaces: - {{- range $v.targetNamespaces }}{{- /* We loop through the list of tergetnamespaces */}} - - {{ . }} - {{- end }}{{- /* End range targetNamespaces */}} - {{- end }}{{- /* End if $v.targetNamespaces */}} - {{- else }} -spec: - targetNamespaces: - - {{ $k }} - {{- end }}{{- /* End of if (hasKey $v "targetNamespaces") */}} - {{- end }}{{- /* range $k, $v := $ns */}} - {{- end }}{{- /* End of if operatorGroup */}} - {{- else if kindIs "string" $ns }} ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: {{ . }}-operator-group - namespace: {{ . }} -spec: - targetNamespaces: - - {{ . }} - {{- end }} {{- /* if kindIs "string" $ns */}} ---- -{{- end }} {{- /* if or (empty $.Values.clusterGroup.operatorgroupExcludes) (not (has . $.Values.clusterGroup.operatorgroupExcludes)) */}} -{{- end }} {{- /* range $ns := .Values.clusterGroup.namespaces */}} -{{- end }} {{- /* if kindIs "map" $ns */}} -{{- end }} {{- /* if not (eq .Values.enabled "plumbing") */}} diff --git a/clustergroup/templates/core/scheduler.yaml b/clustergroup/templates/core/scheduler.yaml deleted file mode 100644 index 5061065e..00000000 --- a/clustergroup/templates/core/scheduler.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{- if hasKey .Values.clusterGroup "scheduler" }} -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: -{{- toYaml .Values.clusterGroup.scheduler | nindent 2 }} -{{- end -}} -{{- end -}} - diff --git a/clustergroup/templates/core/subscriptions.yaml b/clustergroup/templates/core/subscriptions.yaml deleted file mode 100644 index f58f6c28..00000000 --- a/clustergroup/templates/core/subscriptions.yaml +++ /dev/null @@ -1,73 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{- range .Values.clusterGroup.subscriptions }} -{{- $subs := . }} -{{- $installPlanValue := .installPlanApproval }} - -{{- if $subs.namespaces }} -{{- if not $subs.disabled }} -{{- range .namespaces }} -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: {{ $subs.name }} - namespace: {{ . }} -spec: - name: {{ $subs.name }} - source: {{ default "redhat-operators" $subs.source }} - sourceNamespace: {{ default "openshift-marketplace" $subs.sourceNamespace }} - {{- if $subs.channel }} - channel: {{ $subs.channel }} - {{- end }} - installPlanApproval: {{ coalesce $installPlanValue $.Values.global.options.installPlanApproval }} - {{- if $subs.config }} - {{- if $subs.config.env }} - config: - env: - {{- range $subs.config.env }} - - name: {{ .name }} - value: {{ .value }} - {{- end }} - {{- end }} - {{- end }} - {{- if $.Values.global.options.useCSV }} - startingCSV: {{ $subs.csv }} - {{- else if $subs.csv }} - startingCSV: {{ $subs.csv }} - {{- end }} ---- -{{- end }} -{{- end }} -{{- else if not $subs.disabled }} -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: {{ $subs.name }} - namespace: {{ default "openshift-operators" $subs.namespace }} -spec: - name: {{ $subs.name }} - source: {{ default "redhat-operators" $subs.source }} - sourceNamespace: {{ default "openshift-marketplace" $subs.sourceNamespace }} - {{- if $subs.channel }} - channel: {{ $subs.channel }} - {{- end }} - installPlanApproval: {{ coalesce $installPlanValue $.Values.global.options.installPlanApproval }} - {{- if $subs.config }} - {{- if $subs.config.env }} - config: - env: - {{- range $subs.config.env }} - - name: {{ .name }} - value: {{ .value }} - {{- end }} - {{- end }} - {{- end }} - {{- if $.Values.global.options.useCSV }} - startingCSV: {{ $subs.csv }} - {{- else if $subs.csv }} - startingCSV: {{ $subs.csv }} - {{- end }} ---- -{{- end }} -{{- end }} ---- -{{- end }} diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl deleted file mode 100644 index 88538f88..00000000 --- a/clustergroup/templates/imperative/_helpers.tpl +++ /dev/null @@ -1,125 +0,0 @@ -# Pseudo-code -# 1. Get the pattern's CR -# 2. If there is a secret called vp-private-repo-credentials in the current namespace, fetch it -# 3. If it is an http secret, generate the correct URL -# 4. If it is an ssh secret, create the private ssh key and make sure the git clone works - -{{/* fetch-ca InitContainer */}} -{{- define "imperative.initcontainers.fetch-ca" }} -- name: fetch-ca - image: {{ $.Values.clusterGroup.imperative.image }} - imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; - ls -l /tmp/ca-bundles/ - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles -{{- end }} - -{{/* git-init-ca InitContainer */}} -{{- define "imperative.initcontainers.gitinit-ca" }} -- name: git-init - image: {{ $.Values.clusterGroup.imperative.image }} - imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - - name: ca-bundles - mountPath: /etc/pki/tls/certs - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="{{ $.Values.global.repoURL }}"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode}}` }}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.username | base64decode }}` }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.password | base64decode }}` }}')"; - URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode }}` }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - if [ "{{ $.Values.global.targetRevision }}" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch {{ $.Values.global.targetRevision }}"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; -{{- end }} -{{/* Final done container */}} -{{- define "imperative.containers.done" }} -- name: "done" - image: {{ $.Values.clusterGroup.imperative.image }} - imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' -{{- end }} - -{{/* volume-mounts for all containers */}} -{{- define "imperative.volumemounts_ca" }} -- name: git - mountPath: "/git" -- name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml -- mountPath: /var/run/kube-root-ca - name: kube-root-ca -- mountPath: /var/run/trusted-ca - name: trusted-ca-bundle -- mountPath: /var/run/trusted-hub - name: trusted-hub-bundle -- mountPath: /tmp/ca-bundles - name: ca-bundles -{{- end }} - -{{- define "imperative.volumes_ca" }} -- name: git - emptyDir: {} -- name: values-volume - configMap: - name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} -- configMap: - name: kube-root-ca.crt - name: kube-root-ca -- configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle -- configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle -- name: ca-bundles - emptyDir: {} -{{- end }} diff --git a/clustergroup/templates/imperative/auto-approve-installplans.yaml b/clustergroup/templates/imperative/auto-approve-installplans.yaml deleted file mode 100644 index 7b935e77..00000000 --- a/clustergroup/templates/imperative/auto-approve-installplans.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- if $.Values.global.options.autoApproveManualInstallPlans }} ---- -apiVersion: batch/v1 -kind: CronJob -metadata: - name: auto-approve-installplans-cronjob - namespace: {{ $.Values.clusterGroup.imperative.namespace}} -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: {{ $.Values.clusterGroup.imperative.activeDeadlineSeconds }} - template: - metadata: - name: auto-approve-installplans-job - spec: - serviceAccountName: {{ $.Values.clusterGroup.imperative.adminServiceAccountName }} - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} - {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} - - name: auto-approve-installplans - image: {{ $.Values.clusterGroup.imperative.image }} - imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} - env: - - name: HOME - value: /git/home - workingDir: /git/repo - command: - - timeout - - {{ .timeout | default "600" | quote }} - - ansible-playbook - {{- if $.Values.clusterGroup.imperative.verbosity }} - - {{ $.Values.clusterGroup.imperative.verbosity }} - {{- end }} - - -e - - "@/values/values.yaml" - - common/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml - volumeMounts: - {{- include "imperative.volumemounts_ca" . | indent 16 }} - containers: - {{- include "imperative.containers.done" . | indent 12 }} - volumes: - {{- include "imperative.volumes_ca" . | indent 12 }} - restartPolicy: Never -{{- end }} diff --git a/clustergroup/templates/imperative/clusterrole.yaml b/clustergroup/templates/imperative/clusterrole.yaml deleted file mode 100644 index 0ad8ff64..00000000 --- a/clustergroup/templates/imperative/clusterrole.yaml +++ /dev/null @@ -1,37 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{/* This is always defined as we always unseal the cluster with an imperative job */}} -{{- if $.Values.clusterGroup.imperative.serviceAccountCreate }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ $.Values.clusterGroup.imperative.clusterRoleName }} -rules: -{{- if $.Values.clusterGroup.imperative.clusterRoleYaml -}} - {{ toYaml $.Values.clusterGroup.imperative.clusterRoleYaml | nindent 2 }} -{{- else }} - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch -{{- end }} -{{- end }} {{/* if $.Values.clusterGroup.imperative.serviceAccountCreate */}} -{{- if $.Values.clusterGroup.imperative.adminServiceAccountCreate }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ $.Values.clusterGroup.imperative.adminClusterRoleName }} -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' -{{- end }} {{/* if $.Values.clusterGroup.imperative.adminServiceAccountCreate */}} -{{- end }} diff --git a/clustergroup/templates/imperative/configmap.yaml b/clustergroup/templates/imperative/configmap.yaml deleted file mode 100644 index 9f2d6155..00000000 --- a/clustergroup/templates/imperative/configmap.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{/* This is always defined as we always unseal the cluster with an imperative job */}} -{{- $valuesyaml := toYaml $.Values -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} - namespace: {{ $.Values.clusterGroup.imperative.namespace}} -data: - values.yaml: | -{{ tpl $valuesyaml . | indent 4 }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: trusted-ca-bundle - namespace: {{ $.Values.clusterGroup.imperative.namespace}} - annotations: - labels: - config.openshift.io/inject-trusted-cabundle: 'true' -{{- end }} diff --git a/clustergroup/templates/imperative/job.yaml b/clustergroup/templates/imperative/job.yaml deleted file mode 100644 index 55400e8c..00000000 --- a/clustergroup/templates/imperative/job.yaml +++ /dev/null @@ -1,66 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{/* Define this if needed (jobs defined */}} -{{- if (and $.Values.clusterGroup.imperative (gt (len $.Values.clusterGroup.imperative.jobs) 0)) -}} ---- -apiVersion: batch/v1 -kind: CronJob -metadata: - name: {{ $.Values.clusterGroup.imperative.cronJobName }} - namespace: {{ $.Values.clusterGroup.imperative.namespace}} -spec: - schedule: {{ $.Values.clusterGroup.imperative.schedule | quote }} - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: {{ $.Values.clusterGroup.imperative.activeDeadlineSeconds }} - template: - metadata: - name: {{ $.Values.clusterGroup.imperative.jobName }} - spec: - serviceAccountName: {{ $.Values.clusterGroup.imperative.serviceAccountName }} - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} - {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} - {{- range $.Values.clusterGroup.imperative.jobs }} - {{- if ne (.disabled | default "false" | toString | lower ) "true" }} - - name: {{ .name }} - image: {{ .image | default $.Values.clusterGroup.imperative.image }} - imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - {{ .timeout | default "600" | quote }} - - ansible-playbook - {{- if .verbosity }} - - {{ .verbosity }} - {{- end }} - {{- if .tags }} - - -t - - {{ .tags }} - {{- end }} - - -e - - "@/values/values.yaml" - {{- range .extravars }} - - -e - - {{ . | quote }} - {{- end }} - - {{ .playbook }} - volumeMounts: - {{- include "imperative.volumemounts_ca" . | indent 16 }} - {{- end }} - {{- end }} - containers: - {{- include "imperative.containers.done" . | indent 12 }} - volumes: - {{- include "imperative.volumes_ca" . | indent 12 }} - restartPolicy: Never -{{- end }} -{{- end }} diff --git a/clustergroup/templates/imperative/namespace.yaml b/clustergroup/templates/imperative/namespace.yaml deleted file mode 100644 index ee7b8adb..00000000 --- a/clustergroup/templates/imperative/namespace.yaml +++ /dev/null @@ -1,10 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{/* This is always defined as we always unseal the cluster with an imperative job */}} -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: {{ $.Values.clusterGroup.imperative.namespace }} - argocd.argoproj.io/managed-by: {{ $.Values.global.pattern }}-{{ $.Values.clusterGroup.name }} - name: {{ $.Values.clusterGroup.imperative.namespace }} -{{- end }} diff --git a/clustergroup/templates/imperative/rbac.yaml b/clustergroup/templates/imperative/rbac.yaml deleted file mode 100644 index 8bfad5b3..00000000 --- a/clustergroup/templates/imperative/rbac.yaml +++ /dev/null @@ -1,47 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{/* This is always defined as we always unseal the cluster with an imperative job */}} -{{- if $.Values.clusterGroup.imperative.serviceAccountCreate -}} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ $.Values.clusterGroup.imperative.namespace }}-cluster-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ $.Values.clusterGroup.imperative.clusterRoleName }} -subjects: - - kind: ServiceAccount - name: {{ $.Values.clusterGroup.imperative.serviceAccountName }} - namespace: {{ $.Values.clusterGroup.imperative.namespace }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ $.Values.clusterGroup.imperative.namespace }}-rolebinding - namespace: {{ $.Values.clusterGroup.imperative.namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ $.Values.clusterGroup.imperative.roleName }} -subjects: - - kind: ServiceAccount - name: {{ $.Values.clusterGroup.imperative.serviceAccountName }} - namespace: {{ $.Values.clusterGroup.imperative.namespace }} -{{- end }} -{{- if $.Values.clusterGroup.imperative.adminServiceAccountCreate }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ $.Values.clusterGroup.imperative.namespace }}-admin-clusterrolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ $.Values.clusterGroup.imperative.adminClusterRoleName }} -subjects: - - kind: ServiceAccount - name: {{ $.Values.clusterGroup.imperative.adminServiceAccountName }} - namespace: {{ $.Values.clusterGroup.imperative.namespace }} -{{- end }} -{{- end }} diff --git a/clustergroup/templates/imperative/role.yaml b/clustergroup/templates/imperative/role.yaml deleted file mode 100644 index 63ad37d1..00000000 --- a/clustergroup/templates/imperative/role.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{/* This is always defined as we always unseal the cluster with an imperative job */}} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ $.Values.clusterGroup.imperative.roleName }} - namespace: {{ $.Values.clusterGroup.imperative.namespace }} -rules: -{{- if $.Values.clusterGroup.imperative.roleYaml -}} - {{ toYaml $.Values.clusterGroup.imperative.roleYaml | nindent 2 }} -{{- else }} - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' -{{- end }} -{{- end }} diff --git a/clustergroup/templates/imperative/serviceaccount.yaml b/clustergroup/templates/imperative/serviceaccount.yaml deleted file mode 100644 index a171d300..00000000 --- a/clustergroup/templates/imperative/serviceaccount.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -{{/* This is always defined as we always unseal the cluster with an imperative job */}} -{{- if $.Values.clusterGroup.imperative.serviceAccountCreate }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ $.Values.clusterGroup.imperative.serviceAccountName }} - namespace: {{ $.Values.clusterGroup.imperative.namespace }} -{{- end }} -{{- if $.Values.clusterGroup.imperative.adminServiceAccountCreate }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ $.Values.clusterGroup.imperative.adminServiceAccountName }} - namespace: {{ $.Values.clusterGroup.imperative.namespace }} -{{- end }} -{{- end }} diff --git a/clustergroup/templates/imperative/unsealjob.yaml b/clustergroup/templates/imperative/unsealjob.yaml deleted file mode 100644 index a7553da8..00000000 --- a/clustergroup/templates/imperative/unsealjob.yaml +++ /dev/null @@ -1,59 +0,0 @@ -{{/* If the backend is not set at all we default to "vault". See https://www.github.com/helm/helm/issues/3308 - why we avoid using the default function */}} -{{- if or (eq .Values.global.secretStore.backend "vault") (not (hasKey .Values.global.secretStore "backend")) }} -{{- if not (eq .Values.enabled "plumbing") }} -{{- if $.Values.clusterGroup.isHubCluster }} ---- -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: {{ $.Values.clusterGroup.imperative.namespace}} -spec: - schedule: {{ $.Values.clusterGroup.imperative.insecureUnsealVaultInsideClusterSchedule | quote }} - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: {{ $.Values.clusterGroup.imperative.activeDeadlineSeconds }} - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: {{ $.Values.clusterGroup.imperative.serviceAccountName }} - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} - {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} - - name: unseal-playbook - image: {{ $.Values.clusterGroup.imperative.image }} - imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - {{ .timeout | default "600" | quote }} - - ansible-playbook - {{- if $.Values.clusterGroup.imperative.verbosity }} - - {{ $.Values.clusterGroup.imperative.verbosity }} - {{- end }} - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - {{- include "imperative.volumemounts_ca" . | indent 16 }} - containers: - {{- include "imperative.containers.done" . | indent 12 }} - volumes: - {{- include "imperative.volumes_ca" . | indent 12 }} - restartPolicy: Never -{{- end }} -{{- end }} -{{- end }} diff --git a/clustergroup/templates/plumbing/applications.yaml b/clustergroup/templates/plumbing/applications.yaml deleted file mode 100644 index 0b9f4eda..00000000 --- a/clustergroup/templates/plumbing/applications.yaml +++ /dev/null @@ -1,296 +0,0 @@ -{{- if not (eq .Values.enabled "core") }} -{{- $namespace := print $.Values.global.pattern "-" $.Values.clusterGroup.name }} -{{- if (eq .Values.enabled "plumbing") }} -{{- $namespace = "openshift-gitops" }} -{{- end }} -{{- range .Values.clusterGroup.applications }} -{{- if .disabled }} {{- /* This allows us to null out an Application entry by specifying disabled: true in an override file */}} -{{- else if or (.generators) (.generatorFile) (.useGeneratorValues) (.destinationServer) (.destinationNamespace) }} -apiVersion: argoproj.io/v1alpha1 -kind: ApplicationSet -metadata: - name: {{ .name }} - namespace: {{ $namespace }} - labels: - app: {{ .name }} -spec: - {{- if .generators }} - generators: {{ .generators | toPrettyJson }} - {{- else }} - generators: - - git: - repoURL: {{ $.Values.global.repoURL }} - revision: {{ $.Values.global.targetRevision }} - {{- if .generatorFile }} - files: - - path: {{ .generatorFile | quote }} - {{- end }} - {{- end }} - template: - metadata: - name: {{ coalesce .namespace $namespace }} - spec: - project: {{ .project }} - {{- if .syncPolicy }} - syncPolicy: {{ .syncPolicy | toPrettyJson }} - {{- else }} - syncPolicy: - automated: {} - retry: - limit: {{ default 20 $.Values.global.options.applicationRetryLimit }} - {{- end }} - {{- if .ignoreDifferences }} - ignoreDifferences: {{ .ignoreDifferences | toPrettyJson | nindent 2 }} - {{- end }} - source: - repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} - targetRevision: {{ coalesce .targetRevision $.Values.global.targetRevision }} - {{- if .chart }} - chart: {{ .chart }} - {{- end }} - {{- if .path }} - path: {{ .path }} - {{- end }} - {{- if .plugin }} - plugin: {{ .plugin | toPrettyJson }} - {{- end }} - {{- if not .kustomize }} - helm: - ignoreMissingValueFiles: true - valueFiles: - {{- include "clustergroup.app.globalvalues.valuefiles" $ | nindent 12 }} - {{- range $valueFile := $.Values.clusterGroup.sharedValueFiles }} - - {{ tpl $valueFile $ | quote }} - {{- end }} - {{- range $valueFile := .extraValueFiles }} - - {{ tpl $valueFile $ | quote }} - {{- end }} - {{- if .useGeneratorValues }} - values: |- - {{ `{{ values }}` }} - {{- end }} - parameters: - {{- include "clustergroup.app.globalvalues.helmparameters" $ | nindent 12 }} - - name: global.repoURL - value: {{ $.Values.global.repoURL }} - - name: global.targetRevision - value: {{ $.Values.global.targetRevision }} - - name: global.namespace - value: {{ $.Values.global.namespace }} - - name: clusterGroup.name - value: {{ $.Values.clusterGroup.name }} - {{- range .extraHubClusterDomainFields }} - - name: {{ . }} - value: {{ $.Values.global.hubClusterDomain }} - {{- end }} - {{- range .extraLocalClusterDomainFields }} - - name: {{ . }} - value: {{ $.Values.global.localClusterDomain }} - {{- end }} - {{- range .extraRepoURLFields }} - - name: {{ . }} - value: {{ $.Values.global.repoURL }} - {{- end }} - {{- range .extraTargetRevisionFields }} - - name: {{ . }} - value: {{ $.Values.global.targetRevision }} - {{- end }} - {{- range .extraNamespaceFields }} - - name: {{ . }} - value: {{ $.Values.global.namespace }} - {{- end }} - {{- range .extraPatternNameFields }} - - name: {{ . }} - value: {{ $.Values.global.pattern }} - {{- end }} - {{- range $k, $v := $.Values.extraParametersNested }} - - name: {{ $k }} - value: {{ printf "%s" $v | quote }} - {{- end }} - {{- range .overrides }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- if .forceString }} - forceString: true - {{- end }} - {{- end }} - {{- end }} - destination: - server: {{ coalesce .destinationServer "https://kubernetes.default.svc" }} - namespace: {{ coalesce .destinationNamespace .namespace $namespace }} -{{- else }} ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: {{ .name }} - namespace: {{ $namespace }} - labels: - validatedpatterns.io/pattern: {{ $.Values.global.pattern }} - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: {{ $.Values.clusterGroup.targetCluster }} - namespace: {{ default $namespace .namespace }} - project: {{ .project }} - {{- if and .chart .chartVersion }} {{- /* if .chartVersion is set *and* .repoURL is undefined we assume this is a multisource app */}} - sources: - - repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} - {{- /* We do not allow overriding the values with .targetRevision because when we use .targetRevision in a chart to specify the helm - chart, that revision (e.g. 0.0.1) won't exist in the git tree. So here we simply always take the pattern's git branch/commit */}} - targetRevision: {{ $.Values.global.targetRevision }} - ref: patternref - - repoURL: {{ coalesce .repoURL $.Values.global.multiSourceRepoUrl }} - chart: {{ .chart }} - targetRevision: {{ .chartVersion }} - {{- if .plugin }} - plugin: {{ .plugin | toPrettyJson }} - {{- else }} - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - {{- range $k, $v := $.Values.extraParametersNested }} - {{ $k }}: {{ printf "%s" $v | quote }} - {{- end }} - valueFiles: - {{- include "clustergroup.app.globalvalues.prefixedvaluefiles" $ | nindent 8 }} - {{- range $valueFile := $.Values.clusterGroup.sharedValueFiles }} - - {{ tpl $valueFile $ | quote }} - {{- end }} - {{- range $valueFile := .extraValueFiles }} - - {{ tpl $valueFile $ | quote }} - {{- end }} - parameters: - {{- include "clustergroup.app.globalvalues.helmparameters" $ | nindent 8 }} - {{- range .extraHubClusterDomainFields }} - - name: {{ . }} - value: {{ $.Values.global.hubClusterDomain }} - {{- end }} - {{- range .extraLocalClusterDomainFields }} - - name: {{ . }} - value: {{ $.Values.global.localClusterDomain }} - {{- end }} - {{- range .extraRepoURLFields }} - - name: {{ . }} - value: $ARGOCD_APP_SOURCE_REPO_URL - {{- end }} - {{- range .extraTargetRevisionFields }} - - name: {{ . }} - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - {{- end }} - {{- range .extraNamespaceFields }} - - name: {{ . }} - value: $ARGOCD_APP_NAMESPACE - {{- end }} - {{- range .extraPatternNameFields }} - - name: {{ . }} - value: {{ $.Values.global.pattern }} - {{- end }} - {{- range $k, $v := $.Values.extraParametersNested }} - - name: {{ $k }} - value: {{ printf "%s" $v | quote }} - {{- end }} - {{- range .overrides }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- if .forceString }} - forceString: true - {{- end }} - {{- end }}{{- /* range .overrides */}} - {{- if .fileParameters }} - fileParameters: - {{- range .fileParameters }} - - name: {{ .name }} - path: {{ .path }} - {{- end }} - {{- end }}{{- /* if .fileParameters */}} - {{- end }}{{- /* if .plugin */}} - {{- else }} {{- /* if .chartVersion */}} - source: - repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} - targetRevision: {{ coalesce .targetRevision $.Values.global.targetRevision }} - {{- if .chart }} - chart: {{ .chart }} - {{- else }} - path: {{ .path }} - {{- end }}{{- /* if .chart */}} - {{- if .plugin }} - plugin: {{ .plugin | toPrettyJson }} - {{- else if not .kustomize }} - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - {{- range $k, $v := $.Values.extraParametersNested }} - {{ $k }}: {{ printf "%s" $v | quote }} - {{- end }} - valueFiles: - {{- include "clustergroup.app.globalvalues.valuefiles" $ | nindent 6 }} - {{- range $valueFile := $.Values.clusterGroup.sharedValueFiles }} - - {{ tpl $valueFile $ | quote }} - {{- end }} - {{- range $valueFile := .extraValueFiles }} - - {{ tpl $valueFile $ | quote }} - {{- end }} - parameters: - {{- include "clustergroup.app.globalvalues.helmparameters" $ | nindent 8 }} - {{- range .extraHubClusterDomainFields }} - - name: {{ . }} - value: {{ $.Values.global.hubClusterDomain }} - {{- end }} - {{- range .extraLocalClusterDomainFields }} - - name: {{ . }} - value: {{ $.Values.global.localClusterDomain }} - {{- end }} - {{- range .extraRepoURLFields }} - - name: {{ . }} - value: $ARGOCD_APP_SOURCE_REPO_URL - {{- end }} - {{- range .extraTargetRevisionFields }} - - name: {{ . }} - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - {{- end }} - {{- range .extraNamespaceFields }} - - name: {{ . }} - value: $ARGOCD_APP_NAMESPACE - {{- end }} - {{- range .extraPatternNameFields }} - - name: {{ . }} - value: {{ $.Values.global.pattern }} - {{- end }} - {{- range $k, $v := $.Values.extraParametersNested }} - - name: {{ $k }} - value: {{ printf "%s" $v | quote }} - {{- end }} - {{- range .overrides }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- if .forceString }} - forceString: true - {{- end }} - {{- end }}{{- /* range .overrides */}} - {{- if .fileParameters }} - fileParameters: - {{- range .fileParameters }} - - name: {{ .name }} - path: {{ .path }} - {{- end }}{{- /* range .fileParameters */}} - {{- end }}{{- /* if .fileParameters */}} - {{- end }}{{- /* if .plugin */}} - {{- end }}{{- /* if .chartVersion */}} - {{- if .ignoreDifferences }} - ignoreDifferences: {{ .ignoreDifferences | toPrettyJson }} - {{- end }} - {{- if .syncPolicy }} - syncPolicy: {{ .syncPolicy | toPrettyJson }} - {{- else }} - syncPolicy: - automated: {} - retry: - limit: {{ default 20 $.Values.global.applicationRetryLimit }} - {{- end }}{{- /* .syncPolicy */}} -{{- end }}{{- /* if or (.generators) (.generatorFile) (.useGeneratorValues) (.destinationServer) (.destinationNamespace) */}} -{{- end }}{{- /* range .Values.clusterGroup.applications */}} -{{- end }}{{- /* if not (eq .Values.enabled "core") */}} diff --git a/clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml b/clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml deleted file mode 100644 index 6f86c316..00000000 --- a/clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- range $cmp := $.Values.clusterGroup.argoCD.configManagementPlugins }} -{{- if $cmp.pluginConfig }} ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: "argocd-cmp-{{ $cmp.name }}" - namespace: {{ $.Values.global.pattern }}-{{ $.Values.clusterGroup.name }} -data: - "plugin.yaml": | {{ tpl $cmp.pluginConfig $ | nindent 4 }} -{{- end }} -{{- end }} diff --git a/clustergroup/templates/plumbing/argocd-super-role.yaml b/clustergroup/templates/plumbing/argocd-super-role.yaml deleted file mode 100644 index 11366a0b..00000000 --- a/clustergroup/templates/plumbing/argocd-super-role.yaml +++ /dev/null @@ -1,51 +0,0 @@ -{{- if (eq .Values.enabled "all") }} -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }}-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: {{ .Values.clusterGroup.name }}-gitops-argocd-application-controller - namespace: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }} - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: {{ .Values.clusterGroup.name }}-gitops-argocd-server - namespace: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }} - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: {{ .Values.clusterGroup.name }}-gitops-argocd-dex-server - namespace: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }} -{{- end }} diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml deleted file mode 100644 index d7a8f7e3..00000000 --- a/clustergroup/templates/plumbing/argocd.yaml +++ /dev/null @@ -1,207 +0,0 @@ - -{{- if (eq .Values.enabled "all") }} -{{- $namespace := print $.Values.global.pattern "-" $.Values.clusterGroup.name }} -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: {{ .Values.clusterGroup.name }}-gitops - namespace: {{ $namespace }} - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - resourceTrackingMethod: {{ $.Values.clusterGroup.argoCD.resourceTrackingMethod}} - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true - image: {{ $.Values.clusterGroup.imperative.image }} - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles -{{- if len $.Values.clusterGroup.argoCD.initContainers }} -{{ $.Values.clusterGroup.argoCD.initContainers | toPrettyJson }} -{{- end }} -{{- if len $.Values.clusterGroup.argoCD.configManagementPlugins }} - sidecarContainers: -{{- range $cmp := $.Values.clusterGroup.argoCD.configManagementPlugins }} - - name: {{ $cmp.name }} - command: [/var/run/argocd/argocd-cmp-server] -{{- if $cmp.pluginArgs }} - args: {{ $cmp.pluginArgs | toPrettyJson }} -{{- end }} - image: {{ $cmp.image }} - imagePullPolicy: {{ coalesce $cmp.imagePullPolicy "Always" }} - securityContext: - runAsNonRoot: true - volumeMounts: - - mountPath: /var/run/argocd - name: var-files - - mountPath: /home/argocd/cmp-server/plugins - name: plugins - - mountPath: /tmp - name: cmp-tmp -{{- if $cmp.pluginConfig }} - - mountPath: /home/argocd/cmp-server/config/plugin.yaml - subPath: plugin.yaml - name: {{ $cmp.name }} -{{- end }} -{{- end }} -{{- end }} -{{- if len $.Values.clusterGroup.argoCD.configManagementPlugins }} - volumes: - - emptyDir: {} - name: cmp-tmp -{{- range $cmp := $.Values.clusterGroup.argoCD.configManagementPlugins }} - - configMap: - name: "argocd-cmp-{{ $cmp.name }}" - name: {{ $cmp.name }} -{{- end }} -{{- end }} - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi -{{- if $.Values.clusterGroup.argoCD.resourceExclusions }} - resourceExclusions: {{- $.Values.clusterGroup.argoCD.resourceExclusions | toYaml | indent 2 }} -{{- end }} -{{- if .Values.global.excludeESO }} - - apiGroups: - - external-secrets.io - kinds: - - ExternalSecret -{{- end }} - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: {{ .Values.clusterGroup.name }}-gitops-link - namespace: {{ $namespace }} -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://{{ .Values.clusterGroup.name }}-gitops-server-{{ $namespace }}.{{ coalesce .Values.global.localClusterDomain .Values.global.hubClusterDomain }}' - location: ApplicationMenu - text: '{{ title .Values.clusterGroup.name }} ArgoCD' -{{- end }} diff --git a/clustergroup/templates/plumbing/cluster-external-secrets.yaml b/clustergroup/templates/plumbing/cluster-external-secrets.yaml deleted file mode 100644 index 20d6f261..00000000 --- a/clustergroup/templates/plumbing/cluster-external-secrets.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if (eq .Values.enabled "plumbing") }} -{{- $namespace := print $.Values.global.pattern "-" $.Values.clusterGroup.name }} -apiVersion: "external-secrets.io/v1beta1" -kind: ExternalSecret -metadata: - name: {{ .Values.clusterGroup.targetCluster | kebabcase }}-secret - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/sync-wave: "100" -spec: - refreshInterval: 15s - secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} - target: - name: {{ .Values.clusterGroup.targetCluster | kebabcase }}-secret - template: - type: Opaque - metadata: - labels: - argocd.argoproj.io/secret-type: cluster - data: - name: {{ .Values.clusterGroup.targetCluster }} - server: https://api.{{ .Values.global.clusterDomain }}:6443 - config: | - { - "bearerToken": {{ "{{ .kubeBearer | toString | quote }}" }}, - "tlsClientConfig": { - "insecure": false, - "caData": {{ "{{ .kubeCA | toString | quote }}" }} - } - } - data: - - secretKey: kubeBearer - remoteRef: - key: {{ $.Values.clusterGroup.hostedSite.secretsPath }} - property: bearerToken - - secretKey: kubeCA - remoteRef: - key: {{ $.Values.clusterGroup.hostedSite.secretsPath }} - property: caCert -{{- end }} diff --git a/clustergroup/templates/plumbing/gitops-namespace.yaml b/clustergroup/templates/plumbing/gitops-namespace.yaml deleted file mode 100644 index 3cd7608d..00000000 --- a/clustergroup/templates/plumbing/gitops-namespace.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if not (eq .Values.enabled "plumbing") }} -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }} - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }} -spec: {} -{{- end }} diff --git a/clustergroup/templates/plumbing/hosted-sites.yaml b/clustergroup/templates/plumbing/hosted-sites.yaml deleted file mode 100644 index f1f57374..00000000 --- a/clustergroup/templates/plumbing/hosted-sites.yaml +++ /dev/null @@ -1,172 +0,0 @@ -{{- if (eq .Values.enabled "all") }} -{{- range .Values.clusterGroup.managedClusterGroups }} -{{- $group := . }} -{{- if .hostedArgoSites }} -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: {{ .name }} - namespace: openshift-gitops -spec: - description: "Cluster Group {{ $group.name }}" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -{{- end }} -{{- range .hostedArgoSites }} -{{ $secretsPathDefault := print "secret/data/hub/cluster_" .name }} -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: {{ $.Values.global.pattern }}-{{ $group.name }}-{{ .name }} - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: {{ $group.name }} - source: - repoURL: {{ coalesce $group.repoURL $.Values.global.repoURL }} - targetRevision: {{ coalesce $group.targetRevision $.Values.global.targetRevision }} - path: {{ default "common/clustergroup" $group.path }} - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-{{ $group.name }}.yaml" - {{- range $valueFile := $group.extraValueFiles }} - - {{ $valueFile | quote }} - {{- end }} - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: {{ $.Values.global.pattern }} - - name: global.hubClusterDomain - value: {{ $.Values.global.hubClusterDomain }} - - name: global.localClusterDomain - value: apps.{{ .domain }} - - name: global.clusterDomain - value: {{ .domain }} - - name: enabled - value: core - - name: clusterGroup.name - value: {{ $group.name }} - - name: clusterGroup.targetCluster - value: {{ .name }} - - name: clusterGroup.hostedSite.secretsPath - value: {{ default $secretsPathDefault .secretsPath }} - {{- range $group.helmOverrides }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end }} - {{- if $group.fileParameters }} - fileParameters: - {{- range $group.fileParameters }} - - name: {{ .name }} - path: {{ .path }} - {{- end }} - {{- end }} - destination: - name: {{ .name }} - namespace: {{ $.Values.global.pattern }}-{{ $group.name }} - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: {{ $.Values.global.pattern }}-{{ $group.name }}-{{ .name }}-plumbing - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: {{ $group.name }} - source: - repoURL: {{ coalesce $group.repoURL $.Values.global.repoURL }} - targetRevision: {{ coalesce $group.targetRevision $.Values.global.targetRevision }} - path: {{ default "common/clustergroup" $group.path }} - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-{{ $group.name }}.yaml" - {{- range $valueFile := $group.extraValueFiles }} - - {{ $valueFile | quote }} - {{- end }} - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: {{ $.Values.global.pattern }} - - name: global.hubClusterDomain - value: {{ $.Values.global.hubClusterDomain }} - - name: global.localClusterDomain - value: apps.{{ .domain }} - - name: global.clusterDomain - value: {{ .domain }} - - name: enabled - value: plumbing - - name: clusterGroup.name - value: {{ $group.name }} - - name: clusterGroup.targetCluster - value: {{ .name }} - - name: clusterGroup.hostedSite.secretsPath - value: {{ default $secretsPathDefault .secretsPath }} - {{- range $group.helmOverrides }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end }} - {{- if $group.fileParameters }} - fileParameters: - {{- range $group.fileParameters }} - - name: {{ .name }} - path: {{ .path }} - {{- end }} - {{- end }} - destination: - name: in-cluster - namespace: openshift-gitops - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -{{- end }} -{{- end }} -{{- end }} diff --git a/clustergroup/templates/plumbing/projects.yaml b/clustergroup/templates/plumbing/projects.yaml deleted file mode 100644 index 1050f2ee..00000000 --- a/clustergroup/templates/plumbing/projects.yaml +++ /dev/null @@ -1,39 +0,0 @@ -{{- if not (eq .Values.enabled "core") }} -{{- $namespace := print $.Values.global.pattern "-" $.Values.clusterGroup.name }} -{{- /* - We first check if projects are defined as a map. If it is we call - our helper function in _helpers.tpl to process the projects - described in the values file. This is to support issue - https://github.com/validatedpatterns/common/issues/459 created by our customer. -*/ -}} -{{- if kindIs "map" .Values.clusterGroup.projects }} -{{- template "clustergroup.template.plumbing.projects.map" (list .Values.clusterGroup.projects $namespace $.Values.enabled) }} -{{- else }} -{{- range .Values.clusterGroup.projects }} -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: {{ . }} -{{- if (eq $.Values.enabled "plumbing") }} - namespace: openshift-gitops -{{- else }} - namespace: {{ $namespace }} -{{- end }} -spec: - description: "Pattern {{ . }}" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -{{- end }} {{- /* end range */ -}} -{{- end }} {{- /* end if map */ -}} -{{- end }} {{- /* end if not "core" */ -}} diff --git a/clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml b/clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml deleted file mode 100644 index 8b2a9cde..00000000 --- a/clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml +++ /dev/null @@ -1,7 +0,0 @@ -kind: ConfigMap -apiVersion: v1 -metadata: - name: trusted-ca-bundle - namespace: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }} - labels: - config.openshift.io/inject-trusted-cabundle: 'true' diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json deleted file mode 100644 index 08f8c1e5..00000000 --- a/clustergroup/values.schema.json +++ /dev/null @@ -1,1085 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$ref": "#/definitions/ValidatedPatterns", - "definitions": { - "ValidatedPatterns": { - "type": "object", - "additionalProperties": true, - "properties": { - "enabled": { - "type": "string", - "enum": [ - "all", - "core", - "plumbing" - ] - }, - "secretStore": { - "$ref": "#/definitions/SecretStore" - }, - "main": { - "$ref": "#/definitions/Main" - }, - "global": { - "$ref": "#/definitions/Global" - }, - "clusterGroup": { - "$ref": "#/definitions/ClusterGroup" - } - }, - "required": [ - "clusterGroup" - ], - "title": "ValidatedPatterns" - }, - "SecretStore": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "Name of the external secret backend", - "default": "vault-backend" - }, - "kind": { - "type": "string", - "description": "Type of the external secret backend", - "default": "ClusterSecretStore" - } - }, - "required": [ - "name", - "kind" - ], - "title": "SecretsStore" - }, - "Main": { - "type": "object", - "additionalProperties": false, - "required": [ - "clusterGroupName" - ], - "title": "Main", - "description": "This section contains the 'main' variables which are used by the install chart only and are passed to helm via the Makefile", - "properties": { - "clusterGroupName": { - "type": "string" - }, - "extraParameters": { - "type": "array", - "description": "Pass in extra Helm parameters to all ArgoCD Applications and the framework." - }, - "experimentalCapabilities": { - "type": "string", - "description": "String to enable certain experimental capabilities in the operator and the framework." - }, - "git": { - "type": "object", - "additionalProperties": false, - "properties": { - "repoUpstreamURL": { - "type": "string", - "description": "Upstream URL of the pattern's git repository. When set an in-cluster gitea instance gets spawned and repoURL is ignored" - }, - "repoURL": { - "type": "string", - "description": "URL of the pattern's git repository" - }, - "revision": { - "type": "string", - "description": "revision (branch/commit/ref) to use on the pattern's git repository" - } - } - }, - "gitops": { - "type": "object", - "additionalProperties": true, - "properties": { - "channel": { - "type": "string", - "description": "The channel from which to install the gitops operator" - }, - "operatorSource": { - "type": "string", - "description": "The catalog source from which to install the gitops operator" - } - } - }, - "patternsOperator": { - "type": "object", - "additionalProperties": true, - "properties": { - "channel": { - "type": "string", - "description": "The channel from which to install the patterns operator" - }, - "source": { - "type": "string", - "description": "The catalog source from which to install the patterns operator" - } - } - }, - "multiSourceConfig": { - "type": "object", - "additionalProperties": true, - "properties": { - "enabled": { - "type": "boolean", - "description": "Enable the experimental support for multi source for the clustergroup chart" - }, - "helmRepoUrl": { - "type": "string", - "description": "The helm repo URL for the clustergroup chart" - } - } - }, - "analyticsUUID": { - "type": "string", - "description": "UUID used to generate analytics" - } - } - }, - "Global": { - "type": "object", - "additionalProperties": true, - "properties": { - "pattern": { - "type": "string", - "readOnly": true, - "description": "The name of the pattern being installed. The default is the name of the repository's folder and is automatically set by the Makefile" - }, - "clusterDomain": { - "type": "string", - "readOnly": true, - "description": "The FQDN domain of the cluster without the 'apps.' component. For example: mcg-hub.blueprints.rhecoeng.com. Gets set automatically by the framework" - }, - "localClusterDomain": { - "type": "string", - "readOnly": true, - "description": "The FQDN domain of the cluster including the 'apps.' component. For example: apps.mcg-hub.blueprints.rhecoeng.com. Gets set automatically by the framework" - }, - "targetRevision": { - "type": "string", - "readOnly": true, - "description": "revision (branch/commit/ref) to use on the pattern's git repository, it is set automatically by the pattern's operator" - }, - "repoURL": { - "type": "string", - "readOnly": true, - "description": "URL of the pattern's git repository, it is set automatically by the pattern's operator" - }, - "hubClusterDomain": { - "type": "string", - "readOnly": true, - "description": "The FQDN domain of the hub cluster including the 'apps.' component. For example: apps.mcg-hub.blueprints.rhecoeng.com. Gets set automatically by the framework. Only makes sense when using ACM" - }, - "namespace": { - "type": "string", - "readOnly": true, - "description": "The namespace in which the ArgoCD instance is running. Automatically set to either 'openshift-operators' or '$ARGOCD_APP_NAMESPACE'" - }, - "git": { - "$ref": "#/definitions/GlobalGit" - }, - "options": { - "$ref": "#/definitions/Options" - }, - "secretStore": { - "$ref": "#/definitions/GlobalSecretStore" - } - }, - "required": [ - "options" - ], - "title": "Global" - }, - "GlobalSecretStore": { - "type": "object", - "additionalProperties": false, - "properties": { - "backend": { - "type": "string", - "description": "Name of the secrets backend", - "default": "vault" - } - }, - "title": "GlobalSecretsStore" - }, - "GlobalGit": { - "type": "object", - "additionalProperties": true, - "description": "The git configuration used to support Tekton pipeline tasks.", - "properties": { - "hostname": { - "type": "string", - "description": "The hostname for the Git provider being used. e.g. github.com or gitlab.com" - }, - "account": { - "type": "string", - "description": "The account for the Git provider. Accounts allow you to organize and control access to that code. There are three types of accounts on GitHub. Personal accounts Organization accounts Enterprise accounts e.g. hybrid-cloud-patterns or claudiol" - }, - "email": { - "type": "string", - "description": "The contact email for the Git account. e.g. account@gmail.com" - }, - "dev_revision": { - "type": "string", - "deprecated": true, - "description": "This is used by the pipelines as the branch for the development repository. e.g. v2.0. This is marked as deprecated" - } - }, - "required": [ - "hostname", - "account", - "email" - ], - "title": "GlobalGit" - }, - "Options": { - "type": "object", - "additionalProperties": false, - "properties": { - "useCSV": { - "type": "boolean", - "deprecated": true - }, - "syncPolicy": { - "type": "string", - "description": "This is the sync policy for the ArgoCD applications. When set to Automatic ArgoCD will automatically sync an application when it detects differences between the desired manifests in Git." - }, - "installPlanApproval": { - "type": "string", - "deprecated": true, - "description": "This is used to approval strategy for the subscriptions of OpenShift Operators being installed. You can choose Automatic or Manual updates. NOTE: This setting is now available in the subcriptions description in the values file." - }, - "autoApproveManualInstallPlans": { - "type": "boolean", - "description": "This is used to approve automatically those subscriptions of OpenShift Operators that are in Manual with a startingCSV version. You can choose True or False. Defaults: False." - }, - "applicationRetryLimit": { - "type": "integer", - "description": "Number of failed sync attempt retries; unlimited number of attempts if less than 0" - } - }, - "required": [ - "installPlanApproval", - "syncPolicy", - "useCSV" - ], - "title": "Options" - }, - "ClusterGroup": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "The name of the cluster group." - }, - "targetCluster": { - "type": "string" - }, - "isHubCluster": { - "type": "boolean", - "description": "If set to true the values is used to identify whether this is the hub cluster or an edge/spoke cluster configuration." - }, - "sharedValueFiles": { - "type": "array", - "description": "Templated value file paths." - }, - "scheduler": { - "type": "object", - "description": "If set, it will become the spec of the scheduler/cluster in the managed cluster." - }, - "namespaces": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - } - ], - "description": "This is the array of namespaces that the VP framework will create. In addition, operator groups will also be created for each namespace.", - "items": { - "$ref": "#/definitions/Namespaces" - } - }, - "nodes": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - } - ], - "description": "Description of those nodes which ArgoCD will control the labels and/or annotations.", - "items": { - "$ref": "#/definitions/Nodes" - } - }, - "indexImages": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - } - ], - "description": "List of index images for overriding default catalog sources.", - "items": { - "$ref": "#/definitions/IndexImages" - } - }, - "operatorgroupExcludes": { - "type": "array", - "description": "List of namespaces to exclude the creation of operator groups.", - "items": { - "type": "string" - } - }, - "operatorgroupExcludeTargetNS": { - "type": "array", - "description": "Specify the list of namespaces where the target namespace field in the corresponding operatorgroup object should be excluded.", - "items": { - "type": "string" - } - }, - "hostedSite": { - "type": "object", - "items": { - "$ref": "#/definitions/HostedSite" - } - }, - "subscriptions": { - "anyOf": [ - { - "type": "null" - }, - { - "type": "array" - }, - { - "type": "object" - } - ], - "description": "Description of the subscriptions that the VP Framework will install in the cluster. Two ways of defining subscriptions: Using a list or using a dictionary.", - "items": { - "$ref": "#/definitions/Subscription" - } - }, - "projects": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - } - ], - "description": "The list of projects that will be created in the ArgoCD instances.", - "items": { - "type": "string" - } - }, - "applications": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - } - ], - "description": "Description of the applications that will be created in the ArgoCD instances. Two ways of defining applications: Using a list or using a dictionary.", - "items": { - "$ref": "#/definitions/Applications" - } - }, - "argoCD": { - "$ref": "#/definitions/ArgoCD" - }, - "imperative": { - "$ref": "#/definitions/Imperative" - }, - "managedClusterGroups": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "object" - } - ], - "description": "Description of the managed clusters that ACM will be able to manage. Two ways of defining managed clusters: Using a list or using a dictionary.", - "items": { - "$ref": "#/definitions/ManagedClusterGroup" - } - } - }, - "required": [ - "applications", - "isHubCluster", - "name", - "namespaces", - "projects" - ], - "title": "ClusterGroup" - }, - "Namespaces": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ], - "description": "Description of the applications that will be created in the ArgoCD instances. The Application CRD is the Kubernetes resource object representing a deployed application instance in an environment. Two ways of defining applications: Using a list or using a dictionary.", - "additionalProperties": true, - "properties": { - "name": { - "type": "string", - "description": "Name of the namespace." - }, - "labels": { - "type": "array", - "items": { - "$ref": "#/definitions/NameValue" - } - }, - "annotations": { - "type": "array", - "items": { - "$ref": "#/definitions/NameValue" - } - } - } - }, - "Nodes": { - "type": "object", - "description": "Description of those nodes which ArgoCD will control the labels and/or annotations.", - "additionalProperties": true, - "properties": { - "name": { - "type": "string", - "description": "Name of the node." - }, - "labels": { - "type": "array", - "items": { - "$ref": "#/definitions/NameValue" - } - }, - "annotations": { - "type": "array", - "items": { - "$ref": "#/definitions/NameValue" - } - } - } - }, - "NameValue": { - "type": "object", - "description": "Description of the applications that will be created in the ArgoCD instances. The Application CRD is the Kubernetes resource object representing a deployed application instance in an environment. Two ways of defining applications: Using a list or using a dictionary.", - "additionalProperties": true, - "properties": { - "name": { - "type": "string", - "description": "Name of the namespace." - }, - "value": { - "type": "string", - "description": "Name of the namespace." - } - } - }, - "Applications": { - "type": "object", - "description": "Description of the applications that will be created in the ArgoCD instances. The Application CRD is the Kubernetes resource object representing a deployed application instance in an environment. Two ways of defining applications: Using a list or using a dictionary.", - "additionalProperties": true, - "properties": { - "name": { - "type": "string", - "description": "Name of the application in ArgoCD." - }, - "repoURL": { - "type": "string", - "description": "RepoURL is the URL to the repository (Git or Helm) that contains the application manifests." - }, - "targetRevision": { - "type": "string", - "description": "TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version." - }, - "chart": { - "type": "string", - "description": "Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo." - }, - "chartVersion": { - "type": "string", - "description": "The version of the helm chart to be used. Can be a regex like '0.0.*'." - }, - "kustomize": { - "type": "boolean", - "description": "If set to true it will tell ArgoCD to use kustomize to deploy the application." - }, - "plugin": { - "type": "object", - "description": "Plugin holds config management plugin specific options" - }, - "extraValueFiles": { - "type": "array", - "description": "List of extra values files that will be passed to ArgoCD." - }, - "extraHubClusterDomainFields": { - "type": "array", - "description": "List of extra fields that will be passed to ArgoCD." - }, - "extraLocalClusterDomainFields": { - "type": "array", - "description": "List of extra fields that will be passed to ArgoCD." - }, - "extraRepoURLFields": { - "type": "array", - "description": "List of extra fields that will be passed to ArgoCD." - }, - "extraTargetRevisionFields": { - "type": "array", - "description": "List of extra fields that will be passed to ArgoCD." - }, - "extraNamespaceFields": { - "type": "array", - "description": "List of extra fields that will be passed to ArgoCD." - }, - "extraPatternNameFields": { - "type": "array", - "description": "List of extra fields that will be passed to ArgoCD." - }, - "overrides": { - "type": "object" - }, - "fileParameters": { - "type": "array", - "description": "FileParameters are file parameters to the helm template" - }, - "ignoreDifferences": { - "type": "array", - "description": "IgnoreDifferences is a list of resources and their fields which should be ignored during comparison" - }, - "syncPolicy": { - "type": "object", - "description": "SyncPolicy controls when and how a sync will be performed" - }, - "namespace": { - "type": "string", - "description": "Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace" - }, - "project": { - "type": "string", - "description": "Project is a reference to the project this application belongs to. The empty string means that application belongs to the 'default' project." - }, - "path": { - "type": "string", - "description": "Path is a directory path within the Git repository, and is only valid for applications sourced from Git." - } - }, - "required": [ - "name", - "path", - "project" - ], - "title": "Applications" - }, - "ArgoCD": { - "type": "object", - "description": "Details for configuring ArgoCD instances in particular", - "additionalProperties": false, - "properties": { - "configManagementPlugins": { - "type": "array", - "items": { - "$ref": "#/definitions/ArgoCDConfigManagementPlugin" - }, - "description": "The new configManagementPlugins array, will also generate configMaps to inject into the plugins" - }, - "initContainers": { - "type": "array", - "description": "A list of initContainers to add to the repo-server if needed" - }, - "resourceTrackingMethod": { - "type": "string", - "description": "ResourceTrackingMethod defines how Argo CD should track resources that it manages", - "enum": [ - "annotation", - "label", - "annotation+label" - ] - }, - "resourceExclusions": { - "type": "string", - "description": "ResourceExclusions is used to completely ignore entire classes of resource group/kinds." - }, - "resourceHealthChecks": { - "type": "array", - "items": { - "$ref": "#/definitions/ArgoCDResourceHealthChecks" - }, - "description": "ResourceHealthChecks customizes resource health check behavior." - } - } - }, - "ArgoCDConfigManagementPlugin": { - "type": "object", - "additionalProperties": true, - "properties": { - "name": { - "type": "string", - "description": "Name for the config management plugin" - }, - "image": { - "type": "string", - "description": "Image for a sidecar container" - }, - "imagePullPolicy": { - "type": "string", - "description": "Image pull policy for the sidecar. Defaults to 'Always'" - }, - "pluginConfig": { - "type": "string", - "description": "Configuration file to project into sidecar container. This will create a configMap if specified" - }, - "pluginArgs": { - "type": "array", - "description": "Additional args to pass to the cmpserver command, usually loglevel" - } - }, - "required": [ - "name", - "image" - ] - }, - "ArgoCDResourceHealthChecks": { - "type": "object", - "additionalProperties": false, - "properties": { - "check": { - "type": "string" - }, - "group": { - "type": "string" - }, - "kind": { - "type": "string" - } - } - }, - "IndexImages": { - "type": "object", - "description": "Details for overriding default catalog sources", - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "Name for the custom catalog source." - }, - "image": { - "type": "string", - "description": "Location of the index image." - } - } - }, - "HostedSite": { - "type": "object", - "additionalProperties": false, - "properties": { - "secretsPath": { - "type": "string", - "description": "It represents the path in the vault that is supposed to contain two fields: 'bearerToken' representing the token to use to authenticate to the remote cluster and 'caCert' which is the base64-encoded Certificate Authority cert of the remote cluster." - } - }, - "required": [ - "secretsPath" - ], - "title": "HostedSite" - }, - "Imperative": { - "type": "object", - "additionalProperties": false, - "properties": { - "jobs": { - "type": "array", - "items": { - "$ref": "#/definitions/Job" - } - }, - "image": { - "type": "string", - "default": "registry.redhat.io/ansible-automation-platform-22/ee-supported-rhel8:latest" - }, - "namespace": { - "type": "string", - "default": "imperative", - "enum": [ - "imperative" - ] - }, - "serviceAccountCreate": { - "type": "boolean" - }, - "valuesConfigMap": { - "type": "string" - }, - "cronJobName": { - "type": "string" - }, - "jobName": { - "type": "string" - }, - "imagePullPolicy": { - "type": "string", - "default": "Always", - "enum": [ - "Always", - "IfNotPresent", - "Never" - ] - }, - "activeDeadlineSeconds": { - "type": "integer", - "default": 3600 - }, - "schedule": { - "type": "string", - "default": "*/10 * * * *" - }, - "insecureUnsealVaultInsideClusterSchedule": { - "type": "string", - "default": "*/5 * * * *" - }, - "verbosity": { - "type": "string", - "default": "", - "enum": [ - "", - "-v", - "-vv", - "-vvv", - "-vvvv" - ] - }, - "serviceAccountName": { - "type": "string" - }, - "clusterRoleName": { - "type": "string" - }, - "clusterRoleYaml": { - "type": ["string", "array"] - }, - "roleName": { - "type": "string" - }, - "roleYaml": { - "type": "string" - }, - "adminServiceAccountCreate": { - "type": "boolean" - }, - "adminServiceAccountName": { - "type": "string" - }, - "adminClusterRoleName": { - "type": "string" - } - }, - "required": [ - "jobs" - ], - "title": "Imperative" - }, - "Job": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "playbook": { - "type": "string" - }, - "timeout": { - "type": ["integer", "string"] - }, - "image": { - "type": "string", - "default": "registry.redhat.io/ansible-automation-platform-22/ee-supported-rhel8:latest" - }, - "tags": { - "type": "string" - }, - "extravars": { - "type": "array" - }, - "verbosity": { - "type": "string" - } - }, - "required": [ - "name", - "playbook" - ], - "title": "Job" - }, - "ManagedClusterGroup": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "targetRevision": { - "type": "string" - }, - "acmlabels": { - "type": "array", - "items": { - "$ref": "#/definitions/ACMLabels" - } - }, - "hostedArgoSites": { - "type": "array", - "items": { - "$ref": "#/definitions/HostedArgoSites" - } - }, - "clusterPools": { - "type": "object", - "items": { - "$ref": "#/definitions/ClusterPools" - } - }, - "clusterDeployments": { - "type": "object", - "items": { - "$ref": "#/definitions/ClusterDeployments" - } - }, - "clusterSelector": { - "type": "object", - "additionalProperties": true - }, - "helmOverrides": { - "type": "array", - "items": { - "$ref": "#/definitions/HelmOverride" - } - } - }, - "required": [], - "title": "ManagedClusterGroup" - }, - "ClusterPools": { - "type": "object", - "additionalProperties": false, - "properties": { - "size": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "openshiftVersion": { - "type": "string" - }, - "baseDomain": { - "type": "string" - }, - "platform": { - "type": "object", - "$ref": "#/definitions/ClusterPoolsPlatform" - }, - "clusters": { - "type": "array" - } - }, - "required": [ - "name", - "openshiftVersion", - "baseDomain", - "platform", - "clusters" - ], - "title": "ClusterPools" - }, - "ClusterDeployments": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "openshiftVersion": { - "type": "string" - }, - "baseDomain": { - "type": "string" - }, - "platform": { - "type": "object", - "$ref": "#/definitions/ClusterPoolsPlatform" - } - }, - "required": [ - "name", - "openshiftVersion", - "baseDomain", - "platform" - ], - "title": "ClusterDeployments" - }, - "ClusterPoolsPlatform": { - "type": "object", - "additionalProperties": false, - "properties": { - "baseDomainResourceGroupName": { - "type": "string" - }, - "region": { - "type": "string" - } - }, - "required": [ - "region" - ], - "title": "ClusterPoolsPlatform" - }, - "HelmOverride": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "value": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "boolean" - } - ] - } - }, - "required": [ - "name", - "value" - ], - "title": "HelmOverride" - }, - "ACMLabels": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "name", - "value" - ], - "title": "ACMLabels" - }, - "Subscription": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "namespaces": { - "type": "array" - }, - "namespace": { - "type": "string" - }, - "sourceNamespace": { - "type": "string" - }, - "source": { - "type": "string" - }, - "channel": { - "type": "string" - }, - "csv": { - "type": "string" - }, - "installPlanApproval": { - "type": "string", - "enum": [ - "Manual", - "Automatic" - ] - }, - "config": { - "type": "object", - "$ref": "#/definitions/SubscriptionsConfigEnv" - }, - "disabled": { - "type": "boolean" - } - }, - "required": [ - "name" - ], - "title": "Subscription" - }, - "SubscriptionsConfigEnv": { - "type": "array", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "name", - "value" - ], - "title": "SubscriptionsConfigEnv" - }, - "HostedArgoSites": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "domain": { - "type": "string" - }, - "bearerKeyPath": { - "type": "string" - }, - "caKeyPath": { - "type": "string" - } - }, - "required": [ - "name", - "domain" - ], - "title": "HostedArgoSites" - } - } -} diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml deleted file mode 100644 index e40d0cdd..00000000 --- a/clustergroup/values.yaml +++ /dev/null @@ -1,139 +0,0 @@ -global: - extraValueFiles: [] - pattern: common - secretStore: - backend: "vault" - targetRevision: main - options: - useCSV: True - syncPolicy: Automatic - installPlanApproval: Automatic - applicationRetryLimit: 20 - -enabled: "all" - -# Note that sometimes changing helm values might require a hard refresh (https://github.com/helm/helm/issues/3486) -clusterGroup: - name: example - isHubCluster: true - targetCluster: in-cluster - sharedValueFiles: [] - -# scheduler: -# mastersSchedulable: true -# defaultNodeSelector: type=user-node,region=east -# profile: HighNodeUtilization - - argoCD: - initContainers: [] - configManagementPlugins: [] - # resource tracking can be set to annotation, label, or annotation+label - resourceTrackingMethod: label - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - - imperative: - jobs: [] - # This image contains ansible + kubernetes.core by default and is used to run the jobs - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - namespace: "imperative" - # configmap name in the namespace that will contain all helm values - valuesConfigMap: "helm-values-configmap" - cronJobName: "imperative-cronjob" - jobName: "imperative-job" - imagePullPolicy: Always - # This is the maximum timeout of all the jobs (1h) - activeDeadlineSeconds: 3600 - # By default we run this every 10minutes - schedule: "*/10 * * * *" - # Schedule used to trigger the vault unsealing (if explicitely enabled) - # Set to run every 5 minutes in order for load-secrets to succeed within - # a reasonable amount of time (it waits up to 15 mins) - insecureUnsealVaultInsideClusterSchedule: "*/5 * * * *" - # Increase ansible verbosity with '-v' or '-vv..' - verbosity: "" - serviceAccountCreate: true - # service account to be used to run the cron pods - serviceAccountName: imperative-sa - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - roleName: imperative-role - roleYaml: "" - adminServiceAccountCreate: true - adminServiceAccountName: imperative-admin-sa - adminClusterRoleName: imperative-admin-cluster-role - - managedClusterGroups: {} - namespaces: [] -# - name: factory -# # repoURL: https://github.com/dagger-refuse-cool/manuela-factory.git -# # Location of values-global.yaml, values-{name}.yaml, values-{app}.yaml -# targetRevision: main -# path: applications/factory -# helmOverrides: -# - name: clusterGroup.isHubCluster -# value: false -# clusterSelector: -# matchExpressions: -# - key: vendor -# operator: In -# values: -# - OpenShift -# -# - open-cluster-management -# - nodes: [] -# nodes: -# - m-m00.mycluster.domain.tld: -# labels: -# cluster.ocs.openshift.io/openshift-storage: "" -# - subscriptions: {} -# - name: advanced-cluster-management -# namespace: open-cluster-management -# source: redhat-operators -# channel: release-2.3 -# csv: v2.3.2 -# - projects: [] -# - datacenter -# - applications: {} -# - name: acm -# namespace: default -# project: datacenter -# path: applications/acm - -secretStore: - name: vault-backend - kind: ClusterSecretStore - -# Depends on the value of 'vault_hub' ansible variable used -# during the installation -#secretsBase: -# key: secret/data/hub - diff --git a/golang-external-secrets/.github/workflows/update-helm-repo.yml b/golang-external-secrets/.github/workflows/update-helm-repo.yml deleted file mode 100644 index c12af2b5..00000000 --- a/golang-external-secrets/.github/workflows/update-helm-repo.yml +++ /dev/null @@ -1,29 +0,0 @@ -# This invokes the workflow named 'publish-charts' in the umbrella repo -# It expects to have a secret called CHARTS_REPOS_TOKEN which contains -# the GitHub token that has permissions to invoke workflows and commit code -# inside the umbrella-repo. -# The following fine-grained permissions were used in testing and were limited -# to the umbrella repo only: -# - Actions: r/w -# - Commit statuses: r/w -# - Contents: r/w -# - Deployments: r/w -# - Pages: r/w - -name: vp-patterns/update-helm-repo -on: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - -jobs: - helmlint: - uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: - contents: read - - update-helm-repo: - needs: [helmlint] - uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: read-all - secrets: inherit diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml deleted file mode 100644 index 3b3a0133..00000000 --- a/golang-external-secrets/Chart.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v2 -description: A Helm chart to configure the golang-based external-secrets. -keywords: -- pattern -name: golang-external-secrets -version: 0.1.2 -dependencies: - - name: external-secrets - version: "0.10.0" - repository: "https://charts.external-secrets.io" - #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/README.md b/golang-external-secrets/README.md deleted file mode 100644 index b6feb981..00000000 --- a/golang-external-secrets/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Subchart Update - -When updating this sub-chart, please remember to tweak the image tag in values.yaml. -That is because we want to use -ubi images if possible and there is no suffix option, so -we just override the tag with the version + "-ubi" - -## Steps - -1. Edit the version in Chart.yaml -2. Run `helm dependency update .` -3. Run `./update-helm-dependency.sh` -4. Tweak `values.yaml` with the new image versions -5. Run `make test` -6. Commit to Git - -## PRs - -Please send PRs [here](https://github.com/validatedpatterns/common) diff --git a/golang-external-secrets/charts/external-secrets-0.10.0.tgz b/golang-external-secrets/charts/external-secrets-0.10.0.tgz deleted file mode 100644 index 28d7b4a50628a89cf964745ac0dc68cc2f1fdb53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82278 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 f42Q+8;fuD z{~Dfq>=>``Cj642$hviT9!@D(F9nC21%pqRyj9%*7V&*Cidi@wQyNm0+WIl2VVGmq zD{{Wh-oriu0Ml?JqH^<`5;6qqpC9=Qujx^E^%?IH=5nOVOupwod-H*^n*j*nrSS9N z8#auR)bmHtyhH!;?tA{}uStjgl`qam9sEcBnO;mg8K6@b-(p60m{adBetJ2Be@}x? z@b7$rzhi*o{pJ5bjh}-A?}xGH&yJwoSrTJ3C(n14zjaG$g88H}SS-(-;x<3$G$R1mI-(u+p9$9zww?55et;8~fLg44Xi$oDiF!)J}>Gr9~I{ zrGFarG6|qPEvK}&jPDJSp}0lNff|Vx2@rN)TmxY;8>t~i!RYA!|34k3Wof(Nbn88PC1;20xx@dX1)W_P4<`bR;!y)&O z#tF{mF*ASq-hiYm;dMjzs7<6?dm3+mzjPvRPfI>-(#WD@qtsiF9dUU`VHaxXD@EM@ z7k4ayn5GyJu*c0MPzB=T=9`wzG=qhL*-Pu+A1DKGE3`1>Qy&0r>o;M!dT+F5K zA#AM9!U?RTABvJ15q34JLQ(>GfXXk!iAPvqR%L^gdUuR zL%*$=S)qewT3KCAx+O_)vp!;UA&T_jiuB}Onl-{jdyZ&N$X!>Bc#V>RgkgcM9j@Cc zZ4itGp{ntmk%hh1fqc85RKBN2rNXQUC9~K#NrFA4o^n-{N#D7gR=8?bPa9A0%}(6Y zCQge-WQOMx^Qcx7$pMt^i7)+o;($IAG8ASTOhyYH*a#|OY(E!(1JaR`yr*?TdQ52* zVdaV{A{&(6F0ZBC(&G`-sUj!!nQ)cKpB&t4UNjF*>%>GZJ37i)L(r31<)LVM(A*B$ zfDSXe1Fv4Z88vr%XRljbGov5$wJRjlv?NWbumYGPYGwDmF)d^K{CQnvTlZa&esq zf#voRGk_px?nOzzyj;dGO>45wglnE7M_f_JMwJi7XE5e8b7)Ohq;2#h$Dmw~xW=wu zcaS4Md41EW8mC+n*Qj-J>7AC*JQc;mZmfNB>7N>Fpl(J7rD>rYJ{N*aiPY=15VcaK zbph-8@~sPit7TmmK$gtC?ve$~m94r=3r28k9ZobwB~g12w9i2B)E1yvUILzC0ytbW z;QH(!1?~wL3{oOj=Yb5Tt&ipK01mXj&;$!eqPvf|PJ(96L@q40#f(S76Rkc-5sp~y zXx2pQm;iTrWe%wtX^O+bm?OP!fFjvfLyM$#G=ekSc2qPjU1m`#2;`1r1(dT-om2Ho zJGn^V&yEIGMxoD9G0~OpMVQY+ttXOAQ!pmkiN^xLWFEnFoHXbb9QV;LV-R+NS=6Ri z_w0ffJ^wkuMOrPu@`g^rv+NSjWboic=`; zY#%n_I64bauzMt_-=V%uuNw;*a19mr*lSq9S7DIgya9*Oy{}U$>8#5>w?p@ z)Y);hjj6cFt3nLr%?+w=+zOofDx7@J>#K1b%guAgkdP3I5}8Y;N!ebE6HP_Ja#Ib} z^Tc9Z&RQpAU1hJ!KsB=22{4(}&hAo?;(Oc8b;Woj!GKe`0aRo7Zs*Q0jbDU|A%S>{vzEqgy3Jh~@ z(_Dc8jTdiVwR79;N-TGt9+^d+3vEN4grFJga0~$a@JKyQuh{N zPOG?4{?%0e-Mnf{S8H9fs%oQg+Gw0^P~&tRvbJf(G3cVxlH=51Z)En3%wAV!|JEWq zRlHpi`&|*)H!}A|=3ZLnwq%lz!)eMzvX7ZdDEFe2A5^B+@1rE0J0ZO06x{)WyTlvL zmsetclARX7NdBf(#MK60XeZs_8=F8}}l diff --git a/golang-external-secrets/local-patches/0001-runasuser-comment-out.patch b/golang-external-secrets/local-patches/0001-runasuser-comment-out.patch deleted file mode 100644 index 6545881f..00000000 --- a/golang-external-secrets/local-patches/0001-runasuser-comment-out.patch +++ /dev/null @@ -1,48 +0,0 @@ -diff -up external-secrets/values.yaml.orig external-secrets/values.yaml ---- external-secrets/values.yaml.orig 2023-07-31 15:12:18.815909938 +0200 -+++ external-secrets/values.yaml 2023-07-31 15:32:59.905360226 +0200 -@@ -117,9 +117,11 @@ securityContext: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true -- runAsUser: 1000 -- seccompProfile: -- type: RuntimeDefault -+ # runAsUser: 1000 -+ # Uncomment this once 4.10 is out of scope -+ # seccompProfile: -+ # type: RuntimeDefault -+ seccompProfile: null - - resources: {} - # requests: -@@ -331,9 +333,11 @@ webhook: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true -- runAsUser: 1000 -- seccompProfile: -- type: RuntimeDefault -+ # runAsUser: 1000 -+ seccompProfile: null -+ # Uncomment this once 4.10 is out of scope -+ # seccompProfile: -+ # type: RuntimeDefault - - resources: {} - # requests: -@@ -453,9 +457,11 @@ certController: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true -- runAsUser: 1000 -- seccompProfile: -- type: RuntimeDefault -+ # runAsUser: 1000 -+ seccompProfile: null -+ # Uncomment this once 4.10 is out of scope -+ # seccompProfile: -+ # type: RuntimeDefault - - resources: {} - # requests: diff --git a/golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml b/golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml deleted file mode 100644 index a8ab9e78..00000000 --- a/golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml +++ /dev/null @@ -1,23 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets diff --git a/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-role.yaml b/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-role.yaml deleted file mode 100644 index 05ce87a7..00000000 --- a/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-role.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if and (eq .Values.global.secretStore.backend "kubernetes") (eq .Values.clusterGroup.isHubCluster true) }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - namespace: {{ .Values.golangExternalSecrets.kubernetes.remoteNamespace }} - name: golang-external-secrets -rules: -- apiGroups: [""] - resources: - - secrets - verbs: - - get - - list - - watch -- apiGroups: - - authorization.k8s.io - resources: - - selfsubjectrulesreviews - verbs: - - create -{{- end }} diff --git a/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-secretstore.yaml b/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-secretstore.yaml deleted file mode 100644 index 02128e9a..00000000 --- a/golang-external-secrets/templates/kubernetes/golang-external-secrets-hub-secretstore.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if eq .Values.global.secretStore.backend "kubernetes" }} ---- -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: kubernetes-backend - namespace: golang-external-secrets -spec: - provider: - kubernetes: - remoteNamespace: {{ .Values.golangExternalSecrets.kubernetes.remoteNamespace }} - server: - url: {{ .Values.golangExternalSecrets.kubernetes.server.url }} -{{- if .Values.golangExternalSecrets.caProvider.enabled }} -{{- if .Values.clusterGroup.isHubCluster }} - caProvider: - type: {{ .Values.golangExternalSecrets.caProvider.hostCluster.type }} - name: {{ .Values.golangExternalSecrets.caProvider.hostCluster.name }} - key: {{ .Values.golangExternalSecrets.caProvider.hostCluster.key }} - namespace: {{ .Values.golangExternalSecrets.caProvider.hostCluster.namespace }} -{{- else }} - caProvider: - type: {{ .Values.golangExternalSecrets.caProvider.clientCluster.type }} - name: {{ .Values.golangExternalSecrets.caProvider.clientCluster.name }} - key: {{ .Values.golangExternalSecrets.caProvider.clientCluster.key }} - namespace: {{ .Values.golangExternalSecrets.caProvider.clientCluster.namespace }} -{{- end }} -{{- end }} - auth: - serviceAccount: - name: golang-external-secrets - namespace: golang-external-secrets -{{- end }} diff --git a/golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml b/golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml deleted file mode 100644 index 59f55086..00000000 --- a/golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if or (eq .Values.global.secretStore.backend "vault") (not (hasKey .Values.global.secretStore "backend")) }} ---- -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.{{ .Values.global.hubClusterDomain }} - path: secret - # Version of KV backend - version: v2 -{{- if .Values.golangExternalSecrets.caProvider.enabled }} -{{ if .Values.clusterGroup.isHubCluster }} - caProvider: - type: {{ .Values.golangExternalSecrets.caProvider.hostCluster.type }} - name: {{ .Values.golangExternalSecrets.caProvider.hostCluster.name }} - key: {{ .Values.golangExternalSecrets.caProvider.hostCluster.key }} - namespace: {{ .Values.golangExternalSecrets.caProvider.hostCluster.namespace }} -{{ else }} - caProvider: - type: {{ .Values.golangExternalSecrets.caProvider.clientCluster.type }} - name: {{ .Values.golangExternalSecrets.caProvider.clientCluster.name }} - key: {{ .Values.golangExternalSecrets.caProvider.clientCluster.key }} - namespace: {{ .Values.golangExternalSecrets.caProvider.clientCluster.namespace }} -{{ end }} -{{- end }} - auth: - kubernetes: -{{ if .Values.clusterGroup.isHubCluster }} - mountPath: {{ .Values.golangExternalSecrets.vault.mountPath }} - role: {{ .Values.golangExternalSecrets.rbac.rolename }} -{{ else }} - mountPath: {{ $.Values.global.clusterDomain }} - role: {{ $.Values.global.clusterDomain }}-role -{{ end }} - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" -{{- end }} diff --git a/golang-external-secrets/update-helm-dependency.sh b/golang-external-secrets/update-helm-dependency.sh deleted file mode 100755 index 492148eb..00000000 --- a/golang-external-secrets/update-helm-dependency.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -set -eu - -# Get the version of the dependency and then unquote it -TMPVER=$(sed -e '1,/^version:/ d' "Chart.yaml" | grep "version:" | awk '{ print $2 }') -VERSION=$(eval echo "${TMPVER}") - -# Chart format is external-secrets-0.8.0.tgz -NAME="external-secrets" -TAR="${NAME}-${VERSION}.tgz" -CHARTDIR="charts" - -if [ ! -f "${CHARTDIR}/${TAR}" ]; then - echo "Charts $TAR not found" - exit 1 -fi - -pushd "${CHARTDIR}" -rm -rf "${NAME}" -tar xfz "${TAR}" -pushd "${NAME}" -for i in ../../local-patches/*.patch; do - filterdiff "${i}" -p1 -x 'test/*' | patch -p1 -done -find . -type f -iname '*.orig' -exec rm -f "{}" \; -popd -tar cvfz "${TAR}" "${NAME}" -rm -rf "${NAME}" -popd diff --git a/golang-external-secrets/values.yaml b/golang-external-secrets/values.yaml deleted file mode 100644 index 62a6673b..00000000 --- a/golang-external-secrets/values.yaml +++ /dev/null @@ -1,46 +0,0 @@ ---- -golangExternalSecrets: - rbac: - rolename: "hub-role" - - kubernetes: - remoteNamespace: "validated-patterns-secrets" - server: - url: 'https://kubernetes.default' - - vault: - mountPath: "hub" - - # This controls how ESO connects to vault - caProvider: - enabled: true # If vault is exposed via a route that is signed by a non internal CA you might want to disable this - hostCluster: - type: ConfigMap - name: kube-root-ca.crt - key: ca.crt - namespace: golang-external-secrets - clientCluster: - type: Secret - name: hub-ca - key: hub-kube-root-ca.crt - namespace: golang-external-secrets - -global: - hubClusterDomain: hub.example.com - clusterDomain: foo.example.com - - secretStore: - backend: "vault" - -clusterGroup: - isHubCluster: true - -external-secrets: - image: - tag: v0.10.0-ubi - webhook: - image: - tag: v0.10.0-ubi - certController: - image: - tag: v0.10.0-ubi diff --git a/hashicorp-vault/.github/workflows/update-helm-repo.yml b/hashicorp-vault/.github/workflows/update-helm-repo.yml deleted file mode 100644 index c12af2b5..00000000 --- a/hashicorp-vault/.github/workflows/update-helm-repo.yml +++ /dev/null @@ -1,29 +0,0 @@ -# This invokes the workflow named 'publish-charts' in the umbrella repo -# It expects to have a secret called CHARTS_REPOS_TOKEN which contains -# the GitHub token that has permissions to invoke workflows and commit code -# inside the umbrella-repo. -# The following fine-grained permissions were used in testing and were limited -# to the umbrella repo only: -# - Actions: r/w -# - Commit statuses: r/w -# - Contents: r/w -# - Deployments: r/w -# - Pages: r/w - -name: vp-patterns/update-helm-repo -on: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - -jobs: - helmlint: - uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: - contents: read - - update-helm-repo: - needs: [helmlint] - uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: read-all - secrets: inherit diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml deleted file mode 100644 index 09d48391..00000000 --- a/hashicorp-vault/Chart.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v2 -description: A Helm chart to configure Hashicorp's vault. -keywords: -- pattern -name: hashicorp-vault -version: 0.1.2 -dependencies: - - name: vault - version: "0.28.1" - repository: "https://helm.releases.hashicorp.com" diff --git a/hashicorp-vault/README.md b/hashicorp-vault/README.md deleted file mode 100644 index 28362080..00000000 --- a/hashicorp-vault/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# VP hashicorp-vault - -## PRs - -Please send PRs [here](https://github.com/validatedpatterns/common) - -## Updating the chart - -1. Edit Chart.yaml with the new version -2. In the hashicorp-vault folder, run: `helm dependency update .` -3. Run `./update-helm-dependency.sh` -4. Check that the images in ./values.yaml are the same version as [upstream](https://github.com/hashicorp/vault-helm/blob/main/values.openshift.yaml) -5. Git add the new chart in `./charts/vault-.tgz` - -## Patches - -### Issue 674 - -In order to be able to use vault ssl we need to patch the helm chart to fix -upstream issue 674. - -Make sure to run "./update-helm-dependency.sh" after you updated the subchart -(by calling helm dependency update .) - -We can drop this local patch when any one the two conditions is true: - -- [1] is fixed in helm and we can require the version that for installs -- [PR#779](https://github.com/hashicorp/vault-helm/pull/779) is merged in vault-helm *and* our minimum supported OCP version - is OCP 4.11 (route subdomain is broken in OCP < 4.11 due to missing [commit](https://github.com/openshift/router/commit/6f730c7cae966f0ed8def50c81d1bf10fe9eb77b) diff --git a/hashicorp-vault/charts/vault-0.28.1.tgz b/hashicorp-vault/charts/vault-0.28.1.tgz deleted file mode 100644 index ef0f05f52e28759a71fd4a2f08aa88d239748ec8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49807 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 z 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 N=){|%&2WQ-0RUykeRBW+ diff --git a/hashicorp-vault/local-patches/0001-Allow-per-service-annotations.patch b/hashicorp-vault/local-patches/0001-Allow-per-service-annotations.patch deleted file mode 100644 index 796b64cf..00000000 --- a/hashicorp-vault/local-patches/0001-Allow-per-service-annotations.patch +++ /dev/null @@ -1,116 +0,0 @@ -diff -up vault/templates/_helpers.tpl.0.26.1 vault/templates/_helpers.tpl ---- vault/templates/_helpers.tpl.0.26.1 2023-11-07 14:06:52.285821136 +0100 -+++ vault/templates/_helpers.tpl 2023-11-07 14:07:45.445038627 +0100 -@@ -738,6 +738,35 @@ Sets extra vault server Service annotati - {{- end -}} - - {{/* -+Sets extra vault server Service internal annotations -+*/}} -+{{- define "vault.service.internal.annotations" -}} -+ {{- if .Values.server.service.internal.annotations }} -+ {{- $tp := typeOf .Values.server.service.internal.annotations }} -+ {{- if eq $tp "string" }} -+ {{- tpl .Values.server.service.internal.annotations . | nindent 4 }} -+ {{- else }} -+ {{- toYaml .Values.server.service.internal.annotations | nindent 4 }} -+ {{- end }} -+ {{- end }} -+{{- end -}} -+{{/* -+Sets extra vault server Service nonha annotations -+Note: We call it 'nonha' as we need to differentiate the "vault.service.annotations" which are -+ applied to all services -+*/}} -+{{- define "vault.service.nonha.annotations" -}} -+ {{- if .Values.server.service.nonha.annotations }} -+ {{- $tp := typeOf .Values.server.service.nonha.annotations }} -+ {{- if eq $tp "string" }} -+ {{- tpl .Values.server.service.nonha.annotations . | nindent 4 }} -+ {{- else }} -+ {{- toYaml .Values.server.service.nonha.annotations | nindent 4 }} -+ {{- end }} -+ {{- end }} -+{{- end -}} -+ -+{{/* - Sets PodSecurityPolicy annotations - */}} - {{- define "vault.psp.annotations" -}} -diff -up vault/templates/server-headless-service.yaml.0.26.1 vault/templates/server-headless-service.yaml ---- vault/templates/server-headless-service.yaml.0.26.1 2023-11-07 14:08:24.302197609 +0100 -+++ vault/templates/server-headless-service.yaml 2023-11-07 14:08:48.707297472 +0100 -@@ -21,6 +21,7 @@ metadata: - vault-internal: "true" - annotations: - {{ template "vault.service.annotations" .}} -+{{ template "vault.service.internal.annotations" .}} - spec: - {{- if (semverCompare ">= 1.23-0" .Capabilities.KubeVersion.Version) }} - {{- if .Values.server.service.ipFamilyPolicy }} -diff -up vault/templates/server-service.yaml.0.26.1 vault/templates/server-service.yaml ---- vault/templates/server-service.yaml.0.26.1 2023-11-07 14:09:43.152520231 +0100 -+++ vault/templates/server-service.yaml 2023-11-07 14:09:55.406570360 +0100 -@@ -20,6 +20,7 @@ metadata: - app.kubernetes.io/managed-by: {{ .Release.Service }} - annotations: - {{ template "vault.service.annotations" .}} -+{{ template "vault.service.nonha.annotations" .}} - spec: - {{- if .Values.server.service.type}} - type: {{ .Values.server.service.type }} -diff -up vault/values.schema.json.0.26.1 vault/values.schema.json ---- vault/values.schema.json.0.26.1 2023-11-07 14:10:35.177733085 +0100 -+++ vault/values.schema.json 2023-11-07 14:11:52.244048399 +0100 -@@ -931,6 +931,28 @@ - } - } - }, -+ "internal": { -+ "type": "object", -+ "properties": { -+ "annotations": { -+ "type": [ -+ "object", -+ "string" -+ ] -+ } -+ } -+ }, -+ "nonha": { -+ "type": "object", -+ "properties": { -+ "annotations": { -+ "type": [ -+ "object", -+ "string" -+ ] -+ } -+ } -+ }, - "annotations": { - "type": [ - "object", -diff -up vault/values.yaml.0.26.1 vault/values.yaml ---- vault/values.yaml.0.26.1 2023-11-07 14:13:00.865329166 +0100 -+++ vault/values.yaml 2023-11-07 14:14:15.318633813 +0100 -@@ -673,6 +673,19 @@ server: - # YAML-formatted multi-line templated string map of the annotations to apply - # to the standby service. - annotations: {} -+ -+ nonha: -+ # Extra annotations for the service definition. This can either be YAML or a -+ # YAML-formatted multi-line templated string map of the annotations to apply -+ # to the service. -+ annotations: {} -+ -+ internal: -+ # Extra annotations for the service definition. This can either be YAML or a -+ # YAML-formatted multi-line templated string map of the annotations to apply -+ # to the service. -+ annotations: {} -+ - # If enabled, the service selectors will include `app.kubernetes.io/instance: {{ .Release.Name }}` - # When disabled, services may select Vault pods not deployed from the chart. - # Does not affect the headless vault-internal service with `ClusterIP: None` diff --git a/hashicorp-vault/templates/vault-app.yaml b/hashicorp-vault/templates/vault-app.yaml deleted file mode 100644 index bbe16e14..00000000 --- a/hashicorp-vault/templates/vault-app.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.{{ coalesce .Values.global.localClusterDomain .Values.global.hubClusterDomain }}' - location: ApplicationMenu - text: 'Vault' diff --git a/hashicorp-vault/update-helm-dependency.sh b/hashicorp-vault/update-helm-dependency.sh deleted file mode 100755 index 2551d888..00000000 --- a/hashicorp-vault/update-helm-dependency.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -set -eu -o pipefail - -# Get the version of the dependency and then unquote it -TMPVER=$(sed -e '1,/^version:/ d' "Chart.yaml" | grep "version:" | awk '{ print $2 }') -VERSION=$(eval echo "${TMPVER}") - -# Chart format is vault-0.21.0.tgz -NAME="vault" -TAR="${NAME}-${VERSION}.tgz" -CHARTDIR="charts" - -if [ ! -f "${CHARTDIR}/${TAR}" ]; then - echo "Charts $TAR not found" - exit 1 -fi - -pushd "${CHARTDIR}" -rm -rf "${NAME}" -tar xfz "${TAR}" -pushd "${NAME}" -for i in ../../local-patches/*.patch; do - filterdiff "${i}" -p1 -x 'test/*' | patch -p1 -done -find . -type f -iname '*.orig' -exec rm -f "{}" \; -popd -tar cvfz "${TAR}" "${NAME}" -rm -rf "${NAME}" -popd diff --git a/hashicorp-vault/values.yaml b/hashicorp-vault/values.yaml deleted file mode 100644 index 3b16a951..00000000 --- a/hashicorp-vault/values.yaml +++ /dev/null @@ -1,51 +0,0 @@ ---- -global: - openshift: true - localClusterDomain: apps.foo.cluster.com - -vault: - injector: - enabled: false - ui: - enabled: true - server: - extraEnvironmentVars: - VAULT_CACERT: /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt - VAULT_ADDR: https://vault.vault.svc.cluster.local:8200 - standalone: - config: | - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } - - # These are automatically mounted in /vault/userconfig/ - extraVolumes: - - type: secret - name: vault-secret - - service: - enabled: true - nonha: - annotations: - service.beta.openshift.io/serving-cert-secret-name: vault-secret - internal: - annotations: - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal - route: - host: null - enabled: true - tls: - # We cannot use passthrough because you'd be talking to - # https://vault-vault.apps.mcg-hub.blueprints.rhecoeng.com but you'd - # get vault.vault.svc/vault.vault.svc.cluster.local - termination: "reencrypt" - image: - repository: "registry.connect.redhat.com/hashicorp/vault" - tag: "1.17.3-ubi" diff --git a/letsencrypt/.github/workflows/update-helm-repo.yml b/letsencrypt/.github/workflows/update-helm-repo.yml deleted file mode 100644 index c12af2b5..00000000 --- a/letsencrypt/.github/workflows/update-helm-repo.yml +++ /dev/null @@ -1,29 +0,0 @@ -# This invokes the workflow named 'publish-charts' in the umbrella repo -# It expects to have a secret called CHARTS_REPOS_TOKEN which contains -# the GitHub token that has permissions to invoke workflows and commit code -# inside the umbrella-repo. -# The following fine-grained permissions were used in testing and were limited -# to the umbrella repo only: -# - Actions: r/w -# - Commit statuses: r/w -# - Contents: r/w -# - Deployments: r/w -# - Pages: r/w - -name: vp-patterns/update-helm-repo -on: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - -jobs: - helmlint: - uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: - contents: read - - update-helm-repo: - needs: [helmlint] - uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: read-all - secrets: inherit diff --git a/letsencrypt/.helmignore b/letsencrypt/.helmignore deleted file mode 100644 index 0e8a0eb3..00000000 --- a/letsencrypt/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/letsencrypt/Chart.yaml b/letsencrypt/Chart.yaml deleted file mode 100644 index d8a9810f..00000000 --- a/letsencrypt/Chart.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v2 -name: letsencrypt -description: A Helm chart to add letsencrypt support to Validated Patterns. - -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.1 - -# 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 -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "1.16.0" diff --git a/letsencrypt/README.md b/letsencrypt/README.md deleted file mode 100644 index ded97205..00000000 --- a/letsencrypt/README.md +++ /dev/null @@ -1,72 +0,0 @@ -# Letsencrypt support for Validated patterns - -This is an *EXPERIMENTAL* and *UNSUPPORTED* chart to enable letsencrypt support in the pattern. -Currently the only supported cloud for this is AWS. - -In order to enable this chart in your patterns, please add and edit the following lines to `values-AWS.yaml`: - - letsencrypt: - region: eu-central-1 # region of the cluster - server: https://acme-v02.api.letsencrypt.org/directory - # staging URL - # server: https://acme-staging-v02.api.letsencrypt.org/directory - email: foo@bar.it - - clusterGroup: - applications: - letsencrypt: - name: letsencrypt - namespace: letsencrypt - project: default - path: common/letsencrypt - -Once the above is enabled in a pattern, a certain amount of time (~15/20 minutes or so) is needed for all the cluster operators to settle, all the HTTPS routes will have a wildcard certificate signed by letsencrypt. By default also the API endpoint will use a certificate signed by letsencrypt. - -## PRs - -Please send PRs [here](https://github.com/validatedpatterns/common) - -## Limitations - -Please be aware of the following gotchas when using this chart: - -1. Once the API certificate has been replaced with the letsencrypt one, the `oc` commands might fail with x509 unknown certificate authority errors. - You need to remove the previous CA from the kubeconfig file. Run: `oc config set-cluster --certificate-authority="/dev/null" --embed-certs` -2. When you switch to non-staging letsencrypt certificates, things might fail if you asked for too many certificates over the last few days. -3. The cluster takes ~20-30 mins to fully settle when both the API endpoint and the default ingress certificates are implemented - -## Implementation - -This chart creates a Cloud Credential that is allowed to write and read DNS entries via Route53 in AWS. That credential is then used by cert-manager to prove ownership of the DNS zone and answer the ACME DNS01 challenges. -We ask for a single wildcard certificate for the default Ingress *.apps.domain and one non-wildcard certificate for the API endpoint api.domain. -We use Argo's Server-Side Apply feature to patch in the Ingress Controller and the API endpoint certificates. -Currently we also patch the main cluster-wide Argo instance to set the tls route to `reencrypt` in order have a proper cert there. Once issue 297 in the gitops-operator repository is fixed, we can drop that. - -## Parameters - -### global parameters - -This section contains the global parameters consumed by this chart - -| Name | Description | Value | -| --------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------ | -| `global.localClusterDomain` | String containing the domain including the apps. prefix. Gets set by the Validated Pattern framework | `apps.example.com` | - -### letsencrypt parameters - -This section contains all the parameters for the letsencrypt -chart in order to request CA signed certificates in a Validated Pattern - -| Name | Description | Value | -| -------------------------------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | -| `letsencrypt.enabled` | Boolean to enable this feature and request a wildcard cert for the default Infress (*.apps.domain) (defaults to True) | `true` | -| `letsencrypt.api_endpoint` | Boolean to enable letsencrypt certs on the API endpoint too (defaults to True) | `true` | -| `letsencrypt.region` | String that defines the region used by the route53/dns01 resolver in cert-manager (required) | `eu-central-1` | -| `letsencrypt.email` | String containing the email used when requesting certificates to letsencrypt (required) | `test@example.com` | -| `letsencrypt.server` | String containing the letsencrypt ACME URL (Defaults to the staging server) | `https://acme-staging-v02.api.letsencrypt.org/directory` | -| `letsencrypt.organizations` | List of organization names to be put in a certificate (Defaults to [hybrid-cloud-patterns.io]) | `["hybrid-cloud-patterns.io"]` | -| `letsencrypt.usages` | List of certificate uses. See API cert-manager.io/v1.KeyUsage (Defaults to [server auth]) | `["server auth"]` | -| `letsencrypt.duration` | Duration of the requested letsencrypt certificates (Defaults to 168h0m0s) | `168h0m0s` | -| `letsencrypt.renewBefore` | How long before expiration date should the certs be renewed (Defaults to 28h0m0s) | `28h0m0s` | -| `letsencrypt.nameservers` | List of DNS server (ip:port strings) to be used when doing DNS01 challenges (Defaults to [8.8.8.8:53, 1.1.1.1:53]) | `["8.8.8.8:53","1.1.1.1:53"]` | -| `letsencrypt.certmanagerChannel` | String the channel to install cert-manager from (Defaults to "stable-v1") | `stable-v1` | diff --git a/letsencrypt/templates/api-cert.yaml b/letsencrypt/templates/api-cert.yaml deleted file mode 100644 index ed9e7c0e..00000000 --- a/letsencrypt/templates/api-cert.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{ if and (.Values.letsencrypt.enabled) (.Values.letsencrypt.api_endpoint) }} -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: {{ .Values.letsencrypt.duration }} - renewBefore: {{ .Values.letsencrypt.renewBefore }} - commonName: 'api.{{ $.Values.global.localClusterDomain | replace "apps." "" }}' - usages: - {{- range .Values.letsencrypt.usages }} - - {{ . }} - {{- end }} - dnsNames: - - api.{{ $.Values.global.localClusterDomain | replace "apps." "" }} - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - {{- range .Values.letsencrypt.organizations }} - - {{ . }} - {{- end }} -{{- end }} diff --git a/letsencrypt/templates/cert-manager-installation.yaml b/letsencrypt/templates/cert-manager-installation.yaml deleted file mode 100644 index 59375b00..00000000 --- a/letsencrypt/templates/cert-manager-installation.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{ if .Values.letsencrypt.enabled }} ---- -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "{{ .Values.letsencrypt.certmanagerChannel }}" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers={{ with index .Values.letsencrypt.nameservers 0 }}{{ . }}{{- end }},{{ with index .Values.letsencrypt.nameservers 1 }}{{ . }}{{- end }}" - - "--dns01-recursive-nameservers-only" -{{- end }} diff --git a/letsencrypt/templates/credentials-request.yaml b/letsencrypt/templates/credentials-request.yaml deleted file mode 100644 index 27aad295..00000000 --- a/letsencrypt/templates/credentials-request.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{ if .Values.letsencrypt.enabled }} -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager -{{- end }} diff --git a/letsencrypt/templates/default-routes.yaml b/letsencrypt/templates/default-routes.yaml deleted file mode 100644 index 8a01db6a..00000000 --- a/letsencrypt/templates/default-routes.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{ if .Values.letsencrypt.enabled }} ---- -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt -{{ if .Values.letsencrypt.api_endpoint }} ---- -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.{{ $.Values.global.localClusterDomain | replace "apps." "" }} - servingCertificate: - name: api-validated-patterns-letsencrypt-cert -{{- end }} -{{- end }} diff --git a/letsencrypt/templates/issuer.yaml b/letsencrypt/templates/issuer.yaml deleted file mode 100644 index 1370500f..00000000 --- a/letsencrypt/templates/issuer.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{ if .Values.letsencrypt.enabled }} -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: {{ .Values.letsencrypt.server }} - email: {{ .Values.letsencrypt.email }} - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: {{ .Values.letsencrypt.region }} - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key -{{- end }} diff --git a/letsencrypt/templates/namespaces.yaml b/letsencrypt/templates/namespaces.yaml deleted file mode 100644 index a4f65fe5..00000000 --- a/letsencrypt/templates/namespaces.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{ if .Values.letsencrypt.enabled }} -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -{{- end }} diff --git a/letsencrypt/templates/wildcard-cert.yaml b/letsencrypt/templates/wildcard-cert.yaml deleted file mode 100644 index e7b82480..00000000 --- a/letsencrypt/templates/wildcard-cert.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{ if .Values.letsencrypt.enabled }} -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: {{ .Values.letsencrypt.duration }} - renewBefore: {{ .Values.letsencrypt.renewBefore }} - commonName: '*.{{ $.Values.global.localClusterDomain }}' - usages: - {{- range .Values.letsencrypt.usages }} - - {{ . }} - {{- end }} - dnsNames: - - '*.{{ $.Values.global.localClusterDomain }}' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - {{- range .Values.letsencrypt.organizations }} - - {{ . }} - {{- end }} -{{- end }} diff --git a/letsencrypt/values.yaml b/letsencrypt/values.yaml deleted file mode 100644 index a95957b8..00000000 --- a/letsencrypt/values.yaml +++ /dev/null @@ -1,60 +0,0 @@ -# NOTE: This is currently an experimental/unsupported chart! -# Default values for the experimental letsencrypt chart -# Generate the README.md sections using https://github.com/bitnami-labs/readme-generator-for-helm -# -## @section global parameters -## @descriptionStart This section contains the global parameters consumed by this chart -## @descriptionEnd -global: - ## @param global.localClusterDomain String containing the domain including the apps. prefix. Gets set by the Validated Pattern framework - localClusterDomain: "apps.example.com" - -## @section letsencrypt parameters -## @descriptionStart This section contains all the parameters for the letsencrypt -## chart in order to request CA signed certificates in a Validated Pattern -## @descriptionEnd -letsencrypt: - # By default if you include this chart you enable the letsencrypt charts - # on both the *.apps. ingress and on the API endpoint - ## @param letsencrypt.enabled Boolean to enable this feature and request a wildcard cert for the default Infress (*.apps.domain) (defaults to True) - enabled: true - ## @param letsencrypt.api_endpoint Boolean to enable letsencrypt certs on the API endpoint too (defaults to True) - api_endpoint: true - - # These two lines need tweaking for every deployment. @example.com emails - # will be rejected by letsencrypt - ## @param letsencrypt.region String that defines the region used by the route53/dns01 resolver in cert-manager (required) - region: eu-central-1 - ## @param letsencrypt.email String containing the email used when requesting certificates to letsencrypt (required) - email: test@example.com - - # By default we use the staging URL to avoid any ratelimiting while testing - # To switch to the production certificates signed by a recognized CA, please - # switch the comments around in the two following lines - ## @param letsencrypt.server String containing the letsencrypt ACME URL (Defaults to the staging server) - server: https://acme-staging-v02.api.letsencrypt.org/directory - # server: https://acme-v02.api.letsencrypt.org/directory - - # These are only for metadata in the certificates - ## @param letsencrypt.organizations List of organization names to be put in a certificate (Defaults to [hybrid-cloud-patterns.io]) - organizations: - - hybrid-cloud-patterns.io - ## @param letsencrypt.usages List of certificate uses. See API cert-manager.io/v1.KeyUsage (Defaults to [server auth]) - usages: - - server auth - - ## @param letsencrypt.duration Duration of the requested letsencrypt certificates (Defaults to 168h0m0s) - duration: "168h0m0s" - ## @param letsencrypt.renewBefore How long before expiration date should the certs be renewed (Defaults to 28h0m0s) - renewBefore: "28h0m0s" - - # These two are needed because the DNS01 ACME solver needs outside DNS - # servers and won't really work with openshift's internal split-view DNS servers - # https://cert-manager.io/docs/configuration/acme/dns01/#setting-nameservers-for-dns01-self-check - ## @param letsencrypt.nameservers List of DNS server (ip:port strings) to be used when doing DNS01 challenges (Defaults to [8.8.8.8:53, 1.1.1.1:53]) - nameservers: - - 8.8.8.8:53 - - 1.1.1.1:53 - - ## @param letsencrypt.certmanagerChannel String the channel to install cert-manager from (Defaults to "stable-v1") - certmanagerChannel: "stable-v1" From 30f15833ace6022e795b898e17be0a6549b3bbfc Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 6 Sep 2024 15:36:27 +0200 Subject: [PATCH 167/222] README fixes --- Changes.md | 4 ++++ README.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes.md b/Changes.md index 8ade8ad6..e37359b7 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,9 @@ # Changes +## Sep 6, 2024 + +* Most charts have been removed from the tree. To get the charts you now have to point to them + ## Sep 25, 2023 * Upgraded ESO to v0.9.5 diff --git a/README.md b/README.md index 568a2396..95242de3 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ do it manually by doing the following: ```sh git remote add -f upstream-common https://github.com/validatedpatterns/common.git -git merge -s subtree -Xtheirs -Xsubtree=common upstream-common/ha-vault +git merge -s subtree -Xtheirs -Xsubtree=common upstream-common/main ``` ## Secrets From 04dc89f09ea6c1d76ae8f43916232c4456895752 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 6 Sep 2024 16:54:00 +0200 Subject: [PATCH 168/222] Drop the operator-install folder (pattern-install chart) --- operator-install/Chart.yaml | 6 - operator-install/README.md | 8 - ...ops.hybrid-cloud-patterns.io_patterns.yaml | 249 ------------------ .../templates/pattern-operator-configmap.yaml | 13 - operator-install/templates/pattern.yaml | 41 --- operator-install/templates/subscription.yaml | 16 -- operator-install/values.yaml | 38 --- 7 files changed, 371 deletions(-) delete mode 100644 operator-install/Chart.yaml delete mode 100644 operator-install/README.md delete mode 100644 operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml delete mode 100644 operator-install/templates/pattern-operator-configmap.yaml delete mode 100644 operator-install/templates/pattern.yaml delete mode 100644 operator-install/templates/subscription.yaml delete mode 100644 operator-install/values.yaml diff --git a/operator-install/Chart.yaml b/operator-install/Chart.yaml deleted file mode 100644 index 74adcf8f..00000000 --- a/operator-install/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -description: A Helm chart to build and deploy a Cloud Pattern via the patterns operator -keywords: -- pattern -name: pattern-install -version: 0.0.1 diff --git a/operator-install/README.md b/operator-install/README.md deleted file mode 100644 index 588b3d78..00000000 --- a/operator-install/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Update CRD - -In order to update the CRD, copy the following file from the last released -patterns operator version: - -```sh -cp -v patterns-operator/config/crd/bases/gitops.hybrid-cloud-patterns.io_patterns.yaml ./crds/ -``` diff --git a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml b/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml deleted file mode 100644 index 2edacc49..00000000 --- a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml +++ /dev/null @@ -1,249 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: patterns.gitops.hybrid-cloud-patterns.io -spec: - group: gitops.hybrid-cloud-patterns.io - names: - kind: Pattern - listKind: PatternList - plural: patterns - shortNames: - - patt - singular: pattern - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.lastStep - name: Step - priority: 1 - type: string - - jsonPath: .status.lastError - name: Error - priority: 2 - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: Pattern is the Schema for the patterns API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PatternSpec defines the desired state of Pattern - properties: - analyticsUUID: - description: Analytics UUID. Leave empty to autogenerate a random - one. Not PII information - type: string - clusterGroupName: - type: string - experimentalCapabilities: - description: Comma separated capabilities to enable certain experimental - features - type: string - extraParameters: - description: |- - .Name is dot separated per the helm --set syntax, such as: - global.something.field - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - extraValueFiles: - description: URLs to additional Helm parameter files - items: - type: string - type: array - gitOpsSpec: - properties: - manualSync: - description: 'Require manual intervention before Argo will sync - new content. Default: False' - type: boolean - type: object - gitSpec: - properties: - hostname: - description: Optional. FQDN of the git server if automatic parsing - from TargetRepo is broken - type: string - inClusterGitServer: - default: false - description: (EXPERIMENTAL) Enable in-cluster git server (avoids - the need of forking the upstream repository) - type: boolean - originRepo: - description: |- - Upstream git repo containing the pattern to deploy. Used when in-cluster fork to point to the upstream pattern repository. - Takes precedence over TargetRepo - type: string - originRevision: - description: (DEPRECATED) Branch, tag or commit in the upstream - git repository. Does not support short-sha's. Default to HEAD - type: string - pollInterval: - default: 180 - description: 'Interval in seconds to poll for drifts between origin - and target repositories. Default: 180 seconds' - type: integer - targetRepo: - description: Git repo containing the pattern to deploy. Must use - https/http or, for ssh, git@server:foo/bar.git - type: string - targetRevision: - description: 'Branch, tag, or commit to deploy. Does not support - short-sha''s. Default: HEAD' - type: string - tokenSecret: - description: |- - Optional. K8s secret name where the info for connecting to git can be found. The supported secrets are modeled after the - private repositories in argo (https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#repositories) - currently ssh and username+password are supported - type: string - tokenSecretNamespace: - description: Optional. K8s secret namespace where the token for - connecting to git can be found - type: string - type: object - multiSourceConfig: - properties: - clusterGroupChartGitRevision: - default: main - description: |- - The git reference when deploying the clustergroup helm chart directly from a git repo - Defaults to 'main'. (Only used when developing the clustergroup helm chart) - type: string - clusterGroupChartVersion: - description: Which chart version for the clustergroup helm chart. - Defaults to "0.8.*" - type: string - clusterGroupGitRepoUrl: - description: |- - The url when deploying the clustergroup helm chart directly from a git repo - Defaults to '' which means not used (Only used when developing the clustergroup helm chart) - type: string - enabled: - default: true - description: (EXPERIMENTAL) Enable multi-source support when deploying - the clustergroup argo application - type: boolean - helmRepoUrl: - description: The helm chart url to fetch the helm charts from - in order to deploy the pattern. Defaults to https://charts.validatedpatterns.io/ - type: string - type: object - required: - - clusterGroupName - - gitSpec - type: object - status: - description: PatternStatus defines the observed state of Pattern - properties: - analyticsSent: - default: 0 - type: integer - analyticsUUID: - type: string - appClusterDomain: - type: string - applications: - items: - description: |- - PatternApplicationInfo defines the Applications - Status for the Pattern. - This structure is part of the PatternStatus as an array - The Application Status will be included as part of the Observed state of Pattern - properties: - healthMessage: - type: string - healthStatus: - type: string - name: - type: string - namespace: - type: string - syncStatus: - type: string - type: object - type: array - clusterDomain: - type: string - clusterID: - type: string - clusterName: - type: string - clusterPlatform: - type: string - clusterVersion: - type: string - conditions: - items: - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time - type: string - lastUpdateTime: - description: The last time this condition was updated. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of deployment condition. - type: string - required: - - lastUpdateTime - - status - - type - type: object - type: array - lastError: - description: Last error encountered by the pattern - type: string - lastStep: - description: Last action related to the pattern - type: string - path: - type: string - version: - description: Number of updates to the pattern - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/operator-install/templates/pattern-operator-configmap.yaml b/operator-install/templates/pattern-operator-configmap.yaml deleted file mode 100644 index 17b7a026..00000000 --- a/operator-install/templates/pattern-operator-configmap.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: {{ .Values.main.gitops.operatorSource }} - gitops.channel: {{ .Values.main.gitops.channel }} - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml deleted file mode 100644 index 3eda9482..00000000 --- a/operator-install/templates/pattern.yaml +++ /dev/null @@ -1,41 +0,0 @@ -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: {{ .Release.Name }} - namespace: openshift-operators -spec: - clusterGroupName: {{ .Values.main.clusterGroupName }} - gitSpec: -{{- if .Values.main.git.repoUpstreamURL }} - originRepo: {{ .Values.main.git.repoUpstreamURL }} -{{- end }} {{/* if .Values.main.git.repoUpstreamURL */}} - targetRepo: {{ .Values.main.git.repoURL }} - targetRevision: {{ .Values.main.git.revision }} -{{- if and .Values.main.tokenSecret .Values.main.tokenSecretNamespace }} - tokenSecret: {{ .Values.main.tokenSecret }} - tokenSecretNamespace: {{ .Values.main.tokenSecretNamespace }} -{{- end }} {{/* if and .Values.main.tokenSecret .Values.main.tokenSecretNamespace */}} - multiSourceConfig: - enabled: {{ .Values.main.multiSourceConfig.enabled }} -{{- if .Values.main.multiSourceConfig.helmRepoUrl }} - helmRepoUrl: {{ .Values.main.multiSourceConfig.helmRepoUrl }} -{{- end }} {{/* if .Values.main.multiSourceConfig.helmRepoUrl */}} -{{- if .Values.main.analyticsUUID }} - analyticsUUID: {{ .Values.main.analyticsUUID }} -{{- end }} {{/* if .Values.main.analyticsUUID */}} -{{- if .Values.main.experimentalCapabilities }} - experimentalCapabilities: {{ .Values.main.experimentalCapabilities }} -{{- end }} {{/* if .Values.main.experimentalCapabilities */}} -{{- if .Values.main.extraParameters }} - extraParameters: -{{- range .Values.main.extraParameters }} - - name: {{ .name | quote }} - value: {{ .value | quote }} -{{- end }} {{/* range .Values.main.extraParameters */}} -{{- end }} {{/* if .Values.main.extraParameters */}} -{{- if .Values.global.extraValueFiles }} - extraValueFiles: -{{- range .Values.global.extraValueFiles }} - - {{ . | quote }} -{{- end }} {{/* range .Values.global.extraValueFiles */}} -{{- end }} {{/* if .Values.global.extraValueFiles */}} diff --git a/operator-install/templates/subscription.yaml b/operator-install/templates/subscription.yaml deleted file mode 100644 index e8285cae..00000000 --- a/operator-install/templates/subscription.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: {{ .Values.main.patternsOperator.channel }} - installPlanApproval: {{ .Values.main.patternsOperator.installPlanApproval }} - name: patterns-operator - source: {{ .Values.main.patternsOperator.source }} - sourceNamespace: {{ .Values.main.patternsOperator.sourceNamespace }} - {{- if .Values.main.patternsOperator.startingCSV }} - startingCSV: {{ .Values.main.patternsOperator.startingCSV }} - {{- end }} diff --git a/operator-install/values.yaml b/operator-install/values.yaml deleted file mode 100644 index 62c9943a..00000000 --- a/operator-install/values.yaml +++ /dev/null @@ -1,38 +0,0 @@ -global: - extraValueFiles: [] - -main: - git: - # Uncommenting this will set the `originRepo` with the below value - # when `originRepo` is set, an in-cluster gitea will automatically be spawned. - # In this case `originRepo` will point to the upstream repository and `targetRepo` - # will point to the internal in-cluster gitea mirror - # repoUpstreamURL: https://github.com/validatedpatterns/multicloud-gitops - repoURL: https://github.com/pattern-clone/mypattern - revision: main - - gitops: - channel: "gitops-1.13" - operatorSource: redhat-operators - - multiSourceConfig: - enabled: false - # helmRepoUrl: registry.internal.network/helm - - # String to enable certain experimental capabilities in the operator and the - # framework. Not needed unless you know exactly what you're doing. - experimentalCapabilities: "" - - patternsOperator: - channel: fast - source: community-operators - installPlanApproval: Automatic - sourceNamespace: openshift-marketplace - startingCSV: null - - clusterGroupName: default - - # If you are using a private repository define the secret where - # credentials to access the private repository are - # tokenSecret: - # tokenSecretNamespace: From 0226f50fa0a67614d417823e87aa068641795d5b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 6 Sep 2024 16:55:57 +0200 Subject: [PATCH 169/222] Start using the OCI chart in lieu of operator-install --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 785e5307..ca1edf06 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,8 @@ else HELM_OPTS=-f values-global.yaml --set main.tokenSecret=$(TOKEN_SECRET) --set main.tokenSecretNamespace=$(TOKEN_NAMESPACE) --set main.git.repoURL="$(TARGET_CLEAN_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(UUID_HELM_OPTS) $(EXTRA_HELM_OPTS) endif +# Helm does the right thing and fetches all the tags and detects the newest one +PATTERN_INSTALL_CHART ?= oci://quay.io/hybridcloudpatterns/pattern-install ##@ Pattern Common Tasks @@ -54,7 +56,7 @@ help: ## This help message # e.g. from industrial-edge: make -f common/Makefile show .PHONY: show show: ## show the starting template without installing it - helm template common/operator-install/ --name-template $(NAME) $(HELM_OPTS) + helm template $(PATTERN_INSTALL_CHART) --name-template $(NAME) $(HELM_OPTS) preview-all: ## (EXPERIMENTAL) Previews all applications on hub and managed clusters @echo "NOTE: This is just a tentative approximation of rendering all hub and managed clusters templates" @@ -69,7 +71,7 @@ operator-deploy operator-upgrade: validate-prereq validate-origin validate-clust @set -e -o pipefail # Retry five times because the CRD might not be fully installed yet for i in {1..5}; do \ - helm template --include-crds --name-template $(NAME) common/operator-install/ $(HELM_OPTS) | oc apply -f- && break || sleep 10; \ + helm template --include-crds --name-template $(NAME) $(PATTERN_INSTALL_CHART) $(HELM_OPTS) | oc apply -f- && break || sleep 10; \ done .PHONY: uninstall From fe568fba53a5ee12d7b90d5483144b27530ac4da Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 13 Sep 2024 13:54:42 +0200 Subject: [PATCH 170/222] Drop the chart splitting workflows We do not push any changes from common to the chart because they do not exist in common any longer --- .github/workflows/chart-branches.yml | 126 --------------------------- .github/workflows/chart-split.yml | 42 --------- 2 files changed, 168 deletions(-) delete mode 100644 .github/workflows/chart-branches.yml delete mode 100644 .github/workflows/chart-split.yml diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml deleted file mode 100644 index 5ec0ce8f..00000000 --- a/.github/workflows/chart-branches.yml +++ /dev/null @@ -1,126 +0,0 @@ ---- -name: Create per-chart branches - -# We only run this job on the charts that will be later moved to full blown charts -# We also want to run the subtree comand only for the charts that have been actually changed -# because git subtree split is a bit of an expensive operation -# github actions do not support yaml anchors so there is more duplication than usual -on: - push: - branches: - - main - paths: - - 'acm/**' - - 'golang-external-secrets/**' - - 'hashicorp-vault/**' - - 'letsencrypt/**' - - 'clustergroup/**' - - 'operator-install/**' - -jobs: - changes: - name: Figure out per-chart changes - if: github.repository == 'validatedpatterns/common' - runs-on: ubuntu-latest - permissions: read-all - outputs: - acm: ${{ steps.filter.outputs.acm }} - golang-external-secrets: ${{ steps.filter.outputs.golang-external-secrets }} - hashicorp-vault: ${{ steps.filter.outputs.hashicorp-vault }} - letsencrypt: ${{ steps.filter.outputs.letsencrypt }} - clustergroup: ${{ steps.filter.outputs.clustergroup }} - operator-install: ${{ steps.filter.outputs.operator-install }} - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - uses: dorny/paths-filter@v3 - id: filter - with: - filters: | - acm: - - 'acm/**' - golang-external-secrets: - - 'golang-external-secrets/**' - hashicorp-vault: - - 'hashicorp-vault/**' - letsencrypt: - - 'letsencrypt/**' - clustergroup: - - 'clustergroup/**' - operator-install: - - 'operator-install/**' - - acm: - needs: changes - if: ${{ (needs.changes.outputs.acm == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: acm - target_repository: validatedpatterns/acm-chart - secrets: inherit - - golang-external-secrets: - needs: changes - if: ${{ (needs.changes.outputs.golang-external-secrets == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: golang-external-secrets - target_repository: validatedpatterns/golang-external-secrets-chart - secrets: inherit - - hashicorp-vault: - needs: changes - if: ${{ (needs.changes.outputs.hashicorp-vault == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: hashicorp-vault - target_repository: validatedpatterns/hashicorp-vault-chart - secrets: inherit - - letsencrypt: - needs: changes - if: ${{ (needs.changes.outputs.letsencrypt == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: letsencrypt - target_repository: validatedpatterns/letsencrypt-chart - secrets: inherit - - clustergroup: - needs: changes - if: ${{ (needs.changes.outputs.clustergroup == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: clustergroup - target_repository: validatedpatterns/clustergroup-chart - secrets: inherit - - # The folder is named 'operator-install' but the chart is called 'pattern-install' - operator-install: - needs: changes - if: ${{ (needs.changes.outputs.operator-install == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - # The name here is really the folder to be used for the chart - chart_name: operator-install - target_repository: validatedpatterns/pattern-install-chart - secrets: inherit diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml deleted file mode 100644 index 150e419b..00000000 --- a/.github/workflows/chart-split.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -name: Split into chart repo branches - -on: - workflow_call: - inputs: - chart_name: - required: true - type: string - target_repository: - required: true - type: string - -jobs: - split_chart: - runs-on: ubuntu-latest - permissions: - actions: write - contents: write - steps: - - name: Checkout Code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ secrets.CHARTS_REPOS_TOKEN }} - - - name: Run git subtree split and push - env: - GITHUB_TOKEN: ${{ secrets.CHARTS_REPOS_TOKEN }} - run: | - set -e - N="${{ inputs.chart_name }}" - B="${N}-main-single-chart" - GITIMG="quay.io/hybridcloudpatterns/gitsubtree-container:2.40.1" - sudo apt-get update -y && sudo apt-get install -y podman - echo "Running subtree split for ${B}" - podman pull "${GITIMG}" - git push origin -d "${B}" || /bin/true - # Git subtree got broken on recent versions of git hence this container - podman run --net=host --rm -t -v .:/git "${GITIMG}" subtree split -P "${N}" -b "${B}" - #git clone https://validatedpatterns:${GITHUB_TOKEN}@github.com/validatedpatterns/common.git -b "acm-main-single-chart" --single-branch - git push --force https://validatedpatterns:"${GITHUB_TOKEN}"@github.com/${{ inputs.target_repository }}.git "${B}:main" From 554b2eca3aeee365be8b962bcdf593ab2fcbeee2 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 13 Sep 2024 13:58:44 +0200 Subject: [PATCH 171/222] Drop the test folder It used to contain expected tests for the different charts, but those have moved away, so let's start dropping these for now. --- .../acm-industrial-edge-factory.expected.yaml | 363 - tests/acm-industrial-edge-hub.expected.yaml | 735 - tests/acm-medical-diagnosis-hub.expected.yaml | 726 - tests/acm-naked.expected.yaml | 363 - tests/acm-normal.expected.yaml | 1900 --- tests/acm.expected.diff | 651 - ...roup-industrial-edge-factory.expected.yaml | 978 -- ...tergroup-industrial-edge-hub.expected.yaml | 1926 --- ...rgroup-medical-diagnosis-hub.expected.yaml | 2073 --- tests/clustergroup-naked.expected.yaml | 588 - tests/clustergroup-normal.expected.yaml | 1494 -- tests/clustergroup.expected.diff | 381 - ...rets-industrial-edge-factory.expected.yaml | 13143 ---------------- ...-secrets-industrial-edge-hub.expected.yaml | 13143 ---------------- ...ecrets-medical-diagnosis-hub.expected.yaml | 13143 ---------------- ...olang-external-secrets-naked.expected.yaml | 13143 ---------------- ...lang-external-secrets-normal.expected.yaml | 13143 ---------------- tests/golang-external-secrets.expected.diff | 11 - ...ault-industrial-edge-factory.expected.yaml | 410 - ...rp-vault-industrial-edge-hub.expected.yaml | 410 - ...-vault-medical-diagnosis-hub.expected.yaml | 410 - tests/hashicorp-vault-naked.expected.yaml | 410 - tests/hashicorp-vault-normal.expected.yaml | 410 - tests/hashicorp-vault.expected.diff | 11 - ...tall-industrial-edge-factory.expected.yaml | 66 - .../install-industrial-edge-hub.expected.yaml | 66 - ...nstall-medical-diagnosis-hub.expected.yaml | 66 - ...rypt-industrial-edge-factory.expected.yaml | 202 - ...sencrypt-industrial-edge-hub.expected.yaml | 202 - ...ncrypt-medical-diagnosis-hub.expected.yaml | 202 - tests/letsencrypt-naked.expected.yaml | 202 - tests/letsencrypt-normal.expected.yaml | 202 - ...tall-industrial-edge-factory.expected.yaml | 44 - ...-install-industrial-edge-hub.expected.yaml | 44 - ...nstall-medical-diagnosis-hub.expected.yaml | 44 - tests/operator-install-naked.expected.yaml | 44 - tests/operator-install-normal.expected.yaml | 44 - tests/operator-install.expected.diff | 11 - 38 files changed, 81404 deletions(-) delete mode 100644 tests/acm-industrial-edge-factory.expected.yaml delete mode 100644 tests/acm-industrial-edge-hub.expected.yaml delete mode 100644 tests/acm-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/acm-naked.expected.yaml delete mode 100644 tests/acm-normal.expected.yaml delete mode 100644 tests/acm.expected.diff delete mode 100644 tests/clustergroup-industrial-edge-factory.expected.yaml delete mode 100644 tests/clustergroup-industrial-edge-hub.expected.yaml delete mode 100644 tests/clustergroup-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/clustergroup-naked.expected.yaml delete mode 100644 tests/clustergroup-normal.expected.yaml delete mode 100644 tests/clustergroup.expected.diff delete mode 100644 tests/golang-external-secrets-industrial-edge-factory.expected.yaml delete mode 100644 tests/golang-external-secrets-industrial-edge-hub.expected.yaml delete mode 100644 tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/golang-external-secrets-naked.expected.yaml delete mode 100644 tests/golang-external-secrets-normal.expected.yaml delete mode 100644 tests/golang-external-secrets.expected.diff delete mode 100644 tests/hashicorp-vault-industrial-edge-factory.expected.yaml delete mode 100644 tests/hashicorp-vault-industrial-edge-hub.expected.yaml delete mode 100644 tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/hashicorp-vault-naked.expected.yaml delete mode 100644 tests/hashicorp-vault-normal.expected.yaml delete mode 100644 tests/hashicorp-vault.expected.diff delete mode 100644 tests/install-industrial-edge-factory.expected.yaml delete mode 100644 tests/install-industrial-edge-hub.expected.yaml delete mode 100644 tests/install-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/letsencrypt-industrial-edge-factory.expected.yaml delete mode 100644 tests/letsencrypt-industrial-edge-hub.expected.yaml delete mode 100644 tests/letsencrypt-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/letsencrypt-naked.expected.yaml delete mode 100644 tests/letsencrypt-normal.expected.yaml delete mode 100644 tests/operator-install-industrial-edge-factory.expected.yaml delete mode 100644 tests/operator-install-industrial-edge-hub.expected.yaml delete mode 100644 tests/operator-install-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/operator-install-naked.expected.yaml delete mode 100644 tests/operator-install-normal.expected.yaml delete mode 100644 tests/operator-install.expected.diff diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml deleted file mode 100644 index 94c8254f..00000000 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,363 +0,0 @@ ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement-argocd - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy-argocd - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.13 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -# This policy depends on openshift-gitops-policy and the reason is that we need to be -# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance -# because the initcontainer references the trusted-ca-bundle and if it starts without the -# configmap being there we risk running an argo instances that won't trust public CAs -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy-argocd - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - dependencies: - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: openshift-gitops-policy - namespace: open-cluster-management - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: hub-argo-ca-openshift-gitops-policy - namespace: open-cluster-management - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config-argocd - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1beta1 - kind: ArgoCD - metadata: - name: openshift-gitops - namespace: openshift-gitops - spec: - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - webhookServer: - ingress: - enabled: false - route: - enabled: false - controller: - processors: {} - resources: - limits: - cpu: "2" - memory: 2Gi - requests: - cpu: 250m - memory: 1Gi - sharding: {} - grafana: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - route: - enabled: false - ha: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - monitoring: - enabled: false - notifications: - enabled: false - prometheus: - enabled: false - ingress: - enabled: false - route: - enabled: false - rbac: - defaultPolicy: "" - policy: |- - g, system:cluster-admins, role:admin - g, cluster-admins, role:admin - scopes: '[groups]' - redis: - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt - || true - image: registry.redhat.io/ubi9/ubi-minimal:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - resourceExclusions: |- - - apiGroups: - - tekton.dev - clusters: - - '*' - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - service: - type: "" - sso: - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - provider: dex - tls: - ca: {} diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml deleted file mode 100644 index 02f2a8dc..00000000 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,735 +0,0 @@ ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-hub-ca-policy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-hub-ca-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-hub-ca-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-openshift-gitops-policy-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-openshift-gitops-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-factory-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-factory-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-factory-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: factory-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: factory-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: factory-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement-argocd - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy-argocd - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-hub-ca-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-openshift-gitops-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-factory-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: factory-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: { - "matchExpressions": [ - { - "key": "vendor", - "operator": "In", - "values": [ - "OpenShift" - ] - } - ], - "matchLabels": { - "clusterGroup": "factory" - } -} ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-hub-ca-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-hub-ca-config-policy - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: hub-ca - namespace: golang-external-secrets - data: - hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' - hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: imperative - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-openshift-gitops-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: openshift-gitops - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-factory-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-factory-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: mypattern-factory - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: factory-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: factory-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: mypattern-factory - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-factory.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-factory.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - - name: global.clusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - - name: global.clusterVersion - value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - - name: global.localClusterName - value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - - name: global.clusterPlatform - value: aws - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - - name: clusterGroup.name - value: factory - - name: clusterGroup.isHubCluster - value: "false" - destination: - server: https://kubernetes.default.svc - namespace: mypattern-factory - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: 20 - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.13 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -# This policy depends on openshift-gitops-policy and the reason is that we need to be -# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance -# because the initcontainer references the trusted-ca-bundle and if it starts without the -# configmap being there we risk running an argo instances that won't trust public CAs -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy-argocd - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - dependencies: - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: openshift-gitops-policy - namespace: open-cluster-management - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: hub-argo-ca-openshift-gitops-policy - namespace: open-cluster-management - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config-argocd - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1beta1 - kind: ArgoCD - metadata: - name: openshift-gitops - namespace: openshift-gitops - spec: - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - webhookServer: - ingress: - enabled: false - route: - enabled: false - controller: - processors: {} - resources: - limits: - cpu: "2" - memory: 2Gi - requests: - cpu: 250m - memory: 1Gi - sharding: {} - grafana: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - route: - enabled: false - ha: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - monitoring: - enabled: false - notifications: - enabled: false - prometheus: - enabled: false - ingress: - enabled: false - route: - enabled: false - rbac: - defaultPolicy: "" - policy: |- - g, system:cluster-admins, role:admin - g, cluster-admins, role:admin - scopes: '[groups]' - redis: - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt - || true - image: registry.redhat.io/ubi9/ubi-minimal:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - resourceExclusions: |- - - apiGroups: - - tekton.dev - clusters: - - '*' - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - service: - type: "" - sso: - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - provider: dex - tls: - ca: {} diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index 62402c39..00000000 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,726 +0,0 @@ ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-hub-ca-policy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-hub-ca-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-hub-ca-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-openshift-gitops-policy-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-openshift-gitops-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-region-one-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-region-one-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-region-one-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: region-one-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: region-one-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: region-one-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement-argocd - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy-argocd - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-hub-ca-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-openshift-gitops-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-region-one-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: region-one-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: { - "matchLabels": { - "clusterGroup": "region-one" - } -} ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-hub-ca-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-hub-ca-config-policy - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: hub-ca - namespace: golang-external-secrets - data: - hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' - hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: imperative - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-openshift-gitops-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: openshift-gitops - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-region-one-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-region-one-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: mypattern-region-one - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: region-one-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: region-one-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: mypattern-region-one - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-region-one.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-region-one.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - - name: global.clusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - - name: global.clusterVersion - value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - - name: global.localClusterName - value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - - name: global.clusterPlatform - value: aws - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - - name: clusterGroup.name - value: region-one - - name: clusterGroup.isHubCluster - value: "false" - destination: - server: https://kubernetes.default.svc - namespace: mypattern-region-one - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: 20 - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.13 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -# This policy depends on openshift-gitops-policy and the reason is that we need to be -# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance -# because the initcontainer references the trusted-ca-bundle and if it starts without the -# configmap being there we risk running an argo instances that won't trust public CAs -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy-argocd - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - dependencies: - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: openshift-gitops-policy - namespace: open-cluster-management - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: hub-argo-ca-openshift-gitops-policy - namespace: open-cluster-management - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config-argocd - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1beta1 - kind: ArgoCD - metadata: - name: openshift-gitops - namespace: openshift-gitops - spec: - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - webhookServer: - ingress: - enabled: false - route: - enabled: false - controller: - processors: {} - resources: - limits: - cpu: "2" - memory: 2Gi - requests: - cpu: 250m - memory: 1Gi - sharding: {} - grafana: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - route: - enabled: false - ha: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - monitoring: - enabled: false - notifications: - enabled: false - prometheus: - enabled: false - ingress: - enabled: false - route: - enabled: false - rbac: - defaultPolicy: "" - policy: |- - g, system:cluster-admins, role:admin - g, cluster-admins, role:admin - scopes: '[groups]' - redis: - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt - || true - image: registry.redhat.io/ubi9/ubi-minimal:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - resourceExclusions: |- - - apiGroups: - - tekton.dev - clusters: - - '*' - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - service: - type: "" - sso: - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - provider: dex - tls: - ca: {} diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml deleted file mode 100644 index 94c8254f..00000000 --- a/tests/acm-naked.expected.yaml +++ /dev/null @@ -1,363 +0,0 @@ ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement-argocd - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy-argocd - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.13 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -# This policy depends on openshift-gitops-policy and the reason is that we need to be -# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance -# because the initcontainer references the trusted-ca-bundle and if it starts without the -# configmap being there we risk running an argo instances that won't trust public CAs -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy-argocd - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - dependencies: - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: openshift-gitops-policy - namespace: open-cluster-management - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: hub-argo-ca-openshift-gitops-policy - namespace: open-cluster-management - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config-argocd - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1beta1 - kind: ArgoCD - metadata: - name: openshift-gitops - namespace: openshift-gitops - spec: - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - webhookServer: - ingress: - enabled: false - route: - enabled: false - controller: - processors: {} - resources: - limits: - cpu: "2" - memory: 2Gi - requests: - cpu: 250m - memory: 1Gi - sharding: {} - grafana: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - route: - enabled: false - ha: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - monitoring: - enabled: false - notifications: - enabled: false - prometheus: - enabled: false - ingress: - enabled: false - route: - enabled: false - rbac: - defaultPolicy: "" - policy: |- - g, system:cluster-admins, role:admin - g, cluster-admins, role:admin - scopes: '[groups]' - redis: - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt - || true - image: registry.redhat.io/ubi9/ubi-minimal:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - resourceExclusions: |- - - apiGroups: - - tekton.dev - clusters: - - '*' - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - service: - type: "" - sso: - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - provider: dex - tls: - ca: {} diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml deleted file mode 100644 index 0c826026..00000000 --- a/tests/acm-normal.expected.yaml +++ /dev/null @@ -1,1900 +0,0 @@ ---- -# Source: acm/templates/provision/clusterdeployment.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: aws-cd-one-w-pool-acm-provision-edge ---- -# Source: acm/templates/provision/clusterdeployment.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: aws-cd-two-wo-pool-acm-provision-on-deploy ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: v1 -kind: Secret -metadata: - name: aws-ap-acm-provision-edge-install-config -data: - # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWFwJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAxCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDAKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTIKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz -type: Opaque ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: v1 -kind: Secret -metadata: - name: azure-us-acm-provision-edge-install-config -data: - # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== -type: Opaque ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: v1 -kind: Secret -metadata: - name: aws-cd-one-w-pool-acm-provision-edge-install-config - namespace: aws-cd-one-w-pool-acm-provision-edge -data: - # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLW9uZS13LXBvb2wnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCmNvbXB1dGU6Ci0gaHlwZXJ0aHJlYWRpbmc6IEVuYWJsZWQKICBhcmNoaXRlY3R1cmU6IGFtZDY0CiAgbmFtZTogJ3dvcmtlcicKICByZXBsaWNhczogMwogIHBsYXRmb3JtOgogICAgYXdzOgogICAgICB0eXBlOiBtNS54bGFyZ2UKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTEKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz -type: Opaque ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: v1 -kind: Secret -metadata: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config - namespace: aws-cd-two-wo-pool-acm-provision-on-deploy -data: - # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLXR3by13by1wb29sJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhd3M6CiAgICByZWdpb246IGFwLXNvdXRoZWFzdC0zCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== -type: Opaque ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterClaim -metadata: - name: 'two-acm-provision-edge' - annotations: - argocd.argoproj.io/sync-wave: "20" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - cluster.open-cluster-management.io/createmanagedcluster: "true" - labels: - clusterClaimName: two-acm-provision-edge - clusterGroup: region -spec: - clusterPoolName: azure-us-acm-provision-edge ---- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterClaim -metadata: - name: 'three-acm-provision-edge' - annotations: - argocd.argoproj.io/sync-wave: "20" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - cluster.open-cluster-management.io/createmanagedcluster: "true" - labels: - clusterClaimName: three-acm-provision-edge - clusterGroup: region -spec: - clusterPoolName: azure-us-acm-provision-edge ---- -# Source: acm/templates/provision/clusterdeployment.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterDeployment -metadata: - name: aws-cd-one-w-pool-acm-provision-edge - namespace: aws-cd-one-w-pool-acm-provision-edge - labels: - vendor: OpenShift - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - baseDomain: blueprints.rhecoeng.com - clusterName: aws-cd-one-w-pool-acm-provision-edge - installAttemptsLimit: 1 - platform: - aws: - credentialsSecretRef: - name: aws-cd-one-w-pool-acm-provision-edge-creds - region: ap-southeast-1 - provisioning: - installConfigSecretRef: - name: aws-cd-one-w-pool-acm-provision-edge-install-config - sshPrivateKeySecretRef: - name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key - imageSetRef: - name: img4.10.18-multi-appsub - pullSecretRef: - name: aws-cd-one-w-pool-acm-provision-edge-pull-secret ---- -# Source: acm/templates/provision/clusterdeployment.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterDeployment -metadata: - name: aws-cd-two-wo-pool-acm-provision-on-deploy - namespace: aws-cd-two-wo-pool-acm-provision-on-deploy - labels: - vendor: OpenShift - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - baseDomain: blueprints.rhecoeng.com - clusterName: aws-cd-two-wo-pool-acm-provision-on-deploy - installAttemptsLimit: 1 - platform: - aws: - credentialsSecretRef: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds - region: ap-southeast-3 - provisioning: - installConfigSecretRef: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config - sshPrivateKeySecretRef: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key - imageSetRef: - name: img4.10.18-multi-appsub - pullSecretRef: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret ---- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterPool -metadata: - name: "aws-ap-acm-provision-edge" - annotations: - argocd.argoproj.io/sync-wave: "10" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - labels: - cloud: aws - region: 'ap-southeast-2' - vendor: OpenShift - cluster.open-cluster-management.io/clusterset: acm-provision-edge -spec: - size: 3 - runningCount: 0 - baseDomain: blueprints.rhecoeng.com - installConfigSecretTemplateRef: - name: aws-ap-acm-provision-edge-install-config - imageSetRef: - name: img4.10.18-multi-appsub - pullSecretRef: - name: aws-ap-acm-provision-edge-pull-secret - skipMachinePools: true # Disable MachinePool as using custom install-config - platform: - aws: - credentialsSecretRef: - name: aws-ap-acm-provision-edge-creds - region: ap-southeast-2 ---- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterPool -metadata: - name: "azure-us-acm-provision-edge" - annotations: - argocd.argoproj.io/sync-wave: "10" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - labels: - cloud: azure - region: 'eastus' - vendor: OpenShift - cluster.open-cluster-management.io/clusterset: acm-provision-edge -spec: - size: 2 - runningCount: 2 - baseDomain: blueprints.rhecoeng.com - installConfigSecretTemplateRef: - name: azure-us-acm-provision-edge-install-config - imageSetRef: - name: img4.10.18-multi-appsub - pullSecretRef: - name: azure-us-acm-provision-edge-pull-secret - skipMachinePools: true # Disable MachinePool as using custom install-config - platform: - azure: - credentialsSecretRef: - name: azure-us-acm-provision-edge-creds - region: eastus ---- -# Source: acm/templates/provision/secrets-aws.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-ap-acm-provision-edge-creds -spec: - dataFrom: - - extract: - # Expects entries called: aws_access_key_id and aws_secret_access_key - key: secret/data/hub/aws - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-ap-acm-provision-edge-creds - creationPolicy: Owner - template: - type: Opaque ---- -# Source: acm/templates/provision/secrets-aws.yaml -# For use when manually creating clusters with ACM -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-ap-acm-provision-edge-infra-creds -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - - secretKey: awsKeyId - remoteRef: - key: secret/data/hub/aws - property: aws_access_key_id - - secretKey: awsAccessKey - remoteRef: - key: secret/data/hub/aws - property: aws_secret_access_key - - secretKey: sshPublicKey - remoteRef: - key: secret/data/hub/publickey - property: content - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-ap-acm-provision-edge-infra-creds - creationPolicy: Owner - template: - type: Opaque - metadata: - labels: - cluster.open-cluster-management.io/credentials: "" - cluster.open-cluster-management.io/type: aws - data: - baseDomain: "blueprints.rhecoeng.com" - pullSecret: |- - {{ .openshiftPullSecret | toString }} - aws_access_key_id: |- - {{ .awsKeyId | toString }} - aws_secret_access_key: |- - {{ .awsAccessKey | toString }} - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} - ssh-publickey: |- - {{ .sshPublicKey | toString }} - httpProxy: "" - httpsProxy: "" - noProxy: "" - additionalTrustBundle: "" ---- -# Source: acm/templates/provision/secrets-aws.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-cd-one-w-pool-acm-provision-edge-creds - namespace: aws-cd-one-w-pool-acm-provision-edge -spec: - dataFrom: - - extract: - # Expects entries called: aws_access_key_id and aws_secret_access_key - key: secret/data/hub/aws - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-cd-one-w-pool-acm-provision-edge-creds - creationPolicy: Owner - template: - type: Opaque ---- -# Source: acm/templates/provision/secrets-aws.yaml -# For use when manually creating clusters with ACM -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-cd-one-w-pool-acm-provision-edge-infra-creds - namespace: aws-cd-one-w-pool-acm-provision-edge -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - - secretKey: awsKeyId - remoteRef: - key: secret/data/hub/aws - property: aws_access_key_id - - secretKey: awsAccessKey - remoteRef: - key: secret/data/hub/aws - property: aws_secret_access_key - - secretKey: sshPublicKey - remoteRef: - key: secret/data/hub/publickey - property: content - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-cd-one-w-pool-acm-provision-edge-infra-creds - creationPolicy: Owner - template: - type: Opaque - metadata: - labels: - cluster.open-cluster-management.io/credentials: "" - cluster.open-cluster-management.io/type: aws - data: - baseDomain: "blueprints.rhecoeng.com" - pullSecret: |- - {{ .openshiftPullSecret | toString }} - aws_access_key_id: |- - {{ .awsKeyId | toString }} - aws_secret_access_key: |- - {{ .awsAccessKey | toString }} - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} - ssh-publickey: |- - {{ .sshPublicKey | toString }} - httpProxy: "" - httpsProxy: "" - noProxy: "" - additionalTrustBundle: "" ---- -# Source: acm/templates/provision/secrets-aws.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds - namespace: aws-cd-two-wo-pool-acm-provision-on-deploy -spec: - dataFrom: - - extract: - # Expects entries called: aws_access_key_id and aws_secret_access_key - key: secret/data/hub/aws - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds - creationPolicy: Owner - template: - type: Opaque ---- -# Source: acm/templates/provision/secrets-aws.yaml -# For use when manually creating clusters with ACM -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds - namespace: aws-cd-two-wo-pool-acm-provision-on-deploy -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - - secretKey: awsKeyId - remoteRef: - key: secret/data/hub/aws - property: aws_access_key_id - - secretKey: awsAccessKey - remoteRef: - key: secret/data/hub/aws - property: aws_secret_access_key - - secretKey: sshPublicKey - remoteRef: - key: secret/data/hub/publickey - property: content - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds - creationPolicy: Owner - template: - type: Opaque - metadata: - labels: - cluster.open-cluster-management.io/credentials: "" - cluster.open-cluster-management.io/type: aws - data: - baseDomain: "blueprints.rhecoeng.com" - pullSecret: |- - {{ .openshiftPullSecret | toString }} - aws_access_key_id: |- - {{ .awsKeyId | toString }} - aws_secret_access_key: |- - {{ .awsAccessKey | toString }} - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} - ssh-publickey: |- - {{ .sshPublicKey | toString }} - httpProxy: "" - httpsProxy: "" - noProxy: "" - additionalTrustBundle: "" ---- -# Source: acm/templates/provision/secrets-azure.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: azure-us-acm-provision-edge-creds -spec: - data: - - secretKey: azureOsServicePrincipal - remoteRef: - key: secret/data/hub/azureOsServicePrincipal - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: azure-us-acm-provision-edge-creds - creationPolicy: Owner - template: - type: Opaque - data: - osServicePrincipal.json: |- - {{ .azureOsServicePrincipal | toString }} ---- -# Source: acm/templates/provision/secrets-azure.yaml -# For use when manually creating clusters with ACM -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: azure-us-acm-provision-edge-infra-creds -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - - secretKey: sshPublicKey - remoteRef: - key: secret/data/hub/publickey - property: content - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - - secretKey: azureOsServicePrincipal - remoteRef: - key: secret/data/hub/azureOsServicePrincipal - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: azure-us-acm-provision-edge-infra-creds - creationPolicy: Owner - template: - type: Opaque - metadata: - labels: - cluster.open-cluster-management.io/credentials: "" - cluster.open-cluster-management.io/type: aws - data: - cloudName: AzurePublicCloud - osServicePrincipal.json: |- - {{ .azureOsServicePrincipal | toString }} - baseDomain: "blueprints.rhecoeng.com" - baseDomainResourceGroupName: "dojo-dns-zones" - pullSecret: |- - {{ .openshiftPullSecret | toString }} - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} - ssh-publickey: |- - {{ .sshPublicKey | toString }} - httpProxy: "" - httpsProxy: "" - noProxy: "" - additionalTrustBundle: "" ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-ap-acm-provision-edge-pull-secret -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-ap-acm-provision-edge-pull-secret - creationPolicy: Owner - template: - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: |- - {{ .openshiftPullSecret | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-ap-acm-provision-edge-ssh-private-key -spec: - data: - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-ap-acm-provision-edge-ssh-private-key - creationPolicy: Owner - template: - type: Opaque - data: - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: azure-us-acm-provision-edge-pull-secret -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: azure-us-acm-provision-edge-pull-secret - creationPolicy: Owner - template: - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: |- - {{ .openshiftPullSecret | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: azure-us-acm-provision-edge-ssh-private-key -spec: - data: - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: azure-us-acm-provision-edge-ssh-private-key - creationPolicy: Owner - template: - type: Opaque - data: - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-cd-one-w-pool-acm-provision-edge-pull-secret - namespace: aws-cd-one-w-pool-acm-provision-edge -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-cd-one-w-pool-acm-provision-edge-pull-secret - creationPolicy: Owner - template: - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: |- - {{ .openshiftPullSecret | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key - namespace: aws-cd-one-w-pool-acm-provision-edge -spec: - data: - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key - creationPolicy: Owner - template: - type: Opaque - data: - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret - namespace: aws-cd-two-wo-pool-acm-provision-on-deploy -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret - creationPolicy: Owner - template: - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: |- - {{ .openshiftPullSecret | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key - namespace: aws-cd-two-wo-pool-acm-provision-on-deploy -spec: - data: - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key - creationPolicy: Owner - template: - type: Opaque - data: - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} ---- -# Source: acm/templates/provision/clusterdeployment.yaml -apiVersion: cluster.open-cluster-management.io/v1 -kind: ManagedCluster -metadata: - labels: - cluster.open-cluster-management.io/clusterset: acm-provision-edge - clusterGroup: region - name: aws-cd-one-w-pool-acm-provision-edge - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - hubAcceptsClient: true ---- -# Source: acm/templates/provision/clusterdeployment.yaml -apiVersion: cluster.open-cluster-management.io/v1 -kind: ManagedCluster -metadata: - labels: - cluster.open-cluster-management.io/clusterset: acm-provision-on-deploy - clusterGroup: acm-provision-on-deploy - name: aws-cd-two-wo-pool-acm-provision-on-deploy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - hubAcceptsClient: true ---- -# Source: acm/templates/provision/managedclusterset.yaml -apiVersion: cluster.open-cluster-management.io/v1beta2 -kind: ManagedClusterSet -metadata: - annotations: - cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-edge-broker - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - name: acm-provision-edge ---- -# Source: acm/templates/provision/managedclusterset.yaml -apiVersion: cluster.open-cluster-management.io/v1beta2 -kind: ManagedClusterSet -metadata: - annotations: - cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-on-deploy-broker - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - name: acm-provision-on-deploy ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-hub-ca-policy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-hub-ca-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-hub-ca-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-openshift-gitops-policy-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-openshift-gitops-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-acm-edge-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-acm-edge-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-acm-edge-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-acm-provision-edge-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-acm-provision-edge-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-acm-provision-edge-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: hub-argo-ca-acm-provision-on-deploy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: hub-argo-ca-acm-provision-on-deploy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: hub-argo-ca-acm-provision-on-deploy-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-edge-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-edge-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-edge-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-provision-edge-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-provision-edge-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-provision-edge-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-provision-on-deploy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-provision-on-deploy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-provision-on-deploy-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement-argocd - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy-argocd - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-hub-ca-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-openshift-gitops-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-acm-edge-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-acm-provision-edge-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: hub-argo-ca-acm-provision-on-deploy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-edge-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchLabels: - clusterGroup: acm-region ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-provision-edge-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchLabels: - clusterGroup: region ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-provision-on-deploy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchLabels: - clusterGroup: acm-provision-on-deploy ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement-argocd - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-hub-ca-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-hub-ca-config-policy - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: hub-ca - namespace: golang-external-secrets - data: - hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' - hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: imperative - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-openshift-gitops-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: openshift-gitops - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-acm-edge-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-acm-edge-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: mypattern-acm-edge - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-acm-provision-edge-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-acm-provision-edge-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: mypattern-acm-provision-edge - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: hub-argo-ca-acm-provision-on-deploy-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: hub-argo-ca-acm-provision-on-deploy-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-hub-bundle - namespace: mypattern-acm-provision-on-deploy - data: - hub-kube-root-ca.crt: | - {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} - hub-openshift-service-ca.crt: | - {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-edge-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-edge-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: mypattern-acm-edge - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-acm-edge.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-edge.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - - name: global.clusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - - name: global.clusterVersion - value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - - name: global.localClusterName - value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - - name: global.clusterPlatform - value: aws - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - - name: clusterGroup.name - value: acm-edge - - name: clusterGroup.isHubCluster - value: "false" - destination: - server: https://kubernetes.default.svc - namespace: mypattern-acm-edge - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: 20 - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-provision-edge-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-provision-edge-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: mypattern-acm-provision-edge - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-acm-provision-edge.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-edge.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - - name: global.clusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - - name: global.clusterVersion - value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - - name: global.localClusterName - value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - - name: global.clusterPlatform - value: aws - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - - name: clusterGroup.name - value: acm-provision-edge - - name: clusterGroup.isHubCluster - value: "false" - destination: - server: https://kubernetes.default.svc - namespace: mypattern-acm-provision-edge - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: 20 - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-provision-on-deploy-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-provision-on-deploy-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: mypattern-acm-provision-on-deploy - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-acm-provision-on-deploy.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-on-deploy.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - - name: global.clusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - - name: global.clusterVersion - value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - - name: global.localClusterName - value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - - name: global.clusterPlatform - value: aws - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - - name: clusterGroup.name - value: acm-provision-on-deploy - destination: - server: https://kubernetes.default.svc - namespace: mypattern-acm-provision-on-deploy - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: 20 - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.13 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -# This policy depends on openshift-gitops-policy and the reason is that we need to be -# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance -# because the initcontainer references the trusted-ca-bundle and if it starts without the -# configmap being there we risk running an argo instances that won't trust public CAs -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy-argocd - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - dependencies: - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: openshift-gitops-policy - namespace: open-cluster-management - - apiVersion: policy.open-cluster-management.io/v1 - compliance: Compliant - kind: Policy - name: hub-argo-ca-openshift-gitops-policy - namespace: open-cluster-management - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config-argocd - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1beta1 - kind: ArgoCD - metadata: - name: openshift-gitops - namespace: openshift-gitops - spec: - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - webhookServer: - ingress: - enabled: false - route: - enabled: false - controller: - processors: {} - resources: - limits: - cpu: "2" - memory: 2Gi - requests: - cpu: 250m - memory: 1Gi - sharding: {} - grafana: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - route: - enabled: false - ha: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - monitoring: - enabled: false - notifications: - enabled: false - prometheus: - enabled: false - ingress: - enabled: false - route: - enabled: false - rbac: - defaultPolicy: "" - policy: |- - g, system:cluster-admins, role:admin - g, cluster-admins, role:admin - scopes: '[groups]' - redis: - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt - || true - image: registry.redhat.io/ubi9/ubi-minimal:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - resourceExclusions: |- - - apiGroups: - - tekton.dev - clusters: - - '*' - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - service: - type: "" - sso: - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - provider: dex - tls: - ca: {} diff --git a/tests/acm.expected.diff b/tests/acm.expected.diff deleted file mode 100644 index 25b35645..00000000 --- a/tests/acm.expected.diff +++ /dev/null @@ -1,651 +0,0 @@ ---- tests/acm-naked.expected.yaml -+++ tests/acm-normal.expected.yaml -@@ -1,6 +1,386 @@ - --- --# Source: acm/templates/policies/application-policies.yaml --# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -+# Source: acm/templates/provision/secrets-common.yaml -+apiVersion: v1 -+kind: Secret -+metadata: -+ name: aws-ap-acm-provision-edge-install-config -+data: -+ # Base64 encoding of install-config yaml -+ install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWFwJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT3BlblNoaWZ0U0ROCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOiB7CiAgImF3cyI6IHsKICAgICJyZWdpb24iOiAiYXAtc291dGhlYXN0LTIiCiAgfQp9CnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== -+type: Opaque -+--- -+# Source: acm/templates/provision/secrets-common.yaml -+apiVersion: v1 -+kind: Secret -+metadata: -+ name: azure-us-acm-provision-edge-install-config -+data: -+ # Base64 encoding of install-config yaml -+ install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT3BlblNoaWZ0U0ROCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOiB7CiAgImF6dXJlIjogewogICAgImJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZSI6ICJkb2pvLWRucy16b25lcyIsCiAgICAicmVnaW9uIjogImVhc3R1cyIKICB9Cn0KcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz -+type: Opaque -+--- -+# Source: acm/templates/provision/clusterpool.yaml -+apiVersion: hive.openshift.io/v1 -+kind: ClusterClaim -+metadata: -+ name: 'one-acm-provision-edge' -+ annotations: -+ argocd.argoproj.io/sync-wave: "20" -+ cluster.open-cluster-management.io/createmanagedcluster: "true" -+ labels: -+ clusterClaimName: one-acm-provision-edge -+ clusterGroup: region -+spec: -+ clusterPoolName: aws-ap -+--- -+# Source: acm/templates/provision/clusterpool.yaml -+apiVersion: hive.openshift.io/v1 -+kind: ClusterClaim -+metadata: -+ name: 'two-acm-provision-edge' -+ annotations: -+ argocd.argoproj.io/sync-wave: "20" -+ cluster.open-cluster-management.io/createmanagedcluster: "true" -+ labels: -+ clusterClaimName: two-acm-provision-edge -+ clusterGroup: region -+spec: -+ clusterPoolName: azure-us -+--- -+# Source: acm/templates/provision/clusterpool.yaml -+apiVersion: hive.openshift.io/v1 -+kind: ClusterClaim -+metadata: -+ name: 'three-acm-provision-edge' -+ annotations: -+ argocd.argoproj.io/sync-wave: "20" -+ cluster.open-cluster-management.io/createmanagedcluster: "true" -+ labels: -+ clusterClaimName: three-acm-provision-edge -+ clusterGroup: region -+spec: -+ clusterPoolName: azure-us -+--- -+# Source: acm/templates/provision/clusterpool.yaml -+apiVersion: hive.openshift.io/v1 -+kind: ClusterPool -+metadata: -+ name: "aws-ap-acm-provision-edge" -+ annotations: -+ argocd.argoproj.io/sync-wave: "10" -+ labels: -+ cloud: aws -+ region: 'ap-southeast-2' -+ vendor: OpenShift -+ cluster.open-cluster-management.io/clusterset: aws-ap -+spec: -+ size: 3 -+ runningCount: 1 -+ baseDomain: blueprints.rhecoeng.com -+ installConfigSecretTemplateRef: -+ name: aws-ap-acm-provision-edge-install-config -+ imageSetRef: -+ name: img4.10.18-x86-64-appsub -+ pullSecretRef: -+ name: aws-ap-acm-provision-edge-pull-secret -+ skipMachinePools: true # Disable MachinePool as using custom install-config -+ platform: -+ aws: -+ credentialsSecretRef: -+ name: aws-ap-acm-provision-edge-creds -+ region: ap-southeast-2 -+--- -+# Source: acm/templates/provision/clusterpool.yaml -+apiVersion: hive.openshift.io/v1 -+kind: ClusterPool -+metadata: -+ name: "azure-us-acm-provision-edge" -+ annotations: -+ argocd.argoproj.io/sync-wave: "10" -+ labels: -+ cloud: azure -+ region: 'eastus' -+ vendor: OpenShift -+ cluster.open-cluster-management.io/clusterset: azure-us -+spec: -+ size: 2 -+ runningCount: 2 -+ baseDomain: blueprints.rhecoeng.com -+ installConfigSecretTemplateRef: -+ name: azure-us-acm-provision-edge-install-config -+ imageSetRef: -+ name: img4.10.18-x86-64-appsub -+ pullSecretRef: -+ name: azure-us-acm-provision-edge-pull-secret -+ skipMachinePools: true # Disable MachinePool as using custom install-config -+ platform: -+ azure: -+ credentialsSecretRef: -+ name: azure-us-acm-provision-edge-creds -+ region: eastus -+--- -+# Source: acm/templates/provision/secrets-aws.yaml -+apiVersion: external-secrets.io/v1beta1 -+kind: ExternalSecret -+metadata: -+ name: aws-ap-acm-provision-edge-creds -+spec: -+ dataFrom: -+ - extract: -+ # Expects entries called: aws_access_key_id and aws_secret_access_key -+ key: secret/data/hub/aws -+ refreshInterval: 24h0m0s -+ secretStoreRef: -+ name: vault-backend -+ kind: ClusterSecretStore -+ target: -+ name: aws-ap-acm-provision-edge-creds -+ creationPolicy: Owner -+ template: -+ type: Opaque -+--- -+# Source: acm/templates/provision/secrets-aws.yaml -+# For use when manually creating clusters with ACM -+apiVersion: external-secrets.io/v1beta1 -+kind: ExternalSecret -+metadata: -+ name: aws-ap-acm-provision-edge-infra-creds -+spec: -+ data: -+ - secretKey: openshiftPullSecret -+ remoteRef: -+ key: secret/data/hub/openshiftPullSecret -+ property: content -+ - secretKey: awsKeyId -+ remoteRef: -+ key: secret/data/hub/aws -+ property: aws_access_key_id -+ - secretKey: awsAccessKey -+ remoteRef: -+ key: secret/data/hub/aws -+ property: aws_secret_access_key -+ - secretKey: sshPublicKey -+ remoteRef: -+ key: secret/data/hub/publickey -+ property: content -+ - secretKey: sshPrivateKey -+ remoteRef: -+ key: secret/data/hub/privatekey -+ property: content -+ refreshInterval: 24h0m0s -+ secretStoreRef: -+ name: vault-backend -+ kind: ClusterSecretStore -+ target: -+ name: aws-ap-acm-provision-edge-infra-creds -+ creationPolicy: Owner -+ template: -+ type: Opaque -+ metadata: -+ labels: -+ cluster.open-cluster-management.io/credentials: "" -+ cluster.open-cluster-management.io/type: aws -+ data: -+ baseDomain: "blueprints.rhecoeng.com" -+ pullSecret: |- -+ {{ .openshiftPullSecret | toString }} -+ aws_access_key_id: |- -+ {{ .awsKeyId | toString }} -+ aws_secret_access_key: |- -+ {{ .awsAccessKey | toString }} -+ ssh-privatekey: |- -+ {{ .sshPrivateKey | toString }} -+ ssh-publickey: |- -+ {{ .sshPublicKey | toString }} -+ httpProxy: "" -+ httpsProxy: "" -+ noProxy: "" -+ additionalTrustBundle: "" -+--- -+# Source: acm/templates/provision/secrets-azure.yaml -+apiVersion: external-secrets.io/v1beta1 -+kind: ExternalSecret -+metadata: -+ name: azure-us-acm-provision-edge-creds -+spec: -+ data: -+ - secretKey: azureOsServicePrincipal -+ remoteRef: -+ key: secret/data/hub/azureOsServicePrincipal -+ property: content -+ refreshInterval: 24h0m0s -+ secretStoreRef: -+ name: vault-backend -+ kind: ClusterSecretStore -+ target: -+ name: azure-us-acm-provision-edge-creds -+ creationPolicy: Owner -+ template: -+ type: Opaque -+ data: -+ osServicePrincipal.json: |- -+ {{ .azureOsServicePrincipal | toString }} -+--- -+# Source: acm/templates/provision/secrets-azure.yaml -+# For use when manually creating clusters with ACM -+apiVersion: external-secrets.io/v1beta1 -+kind: ExternalSecret -+metadata: -+ name: azure-us-acm-provision-edge-infra-creds -+spec: -+ data: -+ - secretKey: openshiftPullSecret -+ remoteRef: -+ key: secret/data/hub/openshiftPullSecret -+ property: content -+ - secretKey: sshPublicKey -+ remoteRef: -+ key: secret/data/hub/publickey -+ property: content -+ - secretKey: sshPrivateKey -+ remoteRef: -+ key: secret/data/hub/privatekey -+ property: content -+ - secretKey: azureOsServicePrincipal -+ remoteRef: -+ key: secret/data/hub/azureOsServicePrincipal -+ property: content -+ refreshInterval: 24h0m0s -+ secretStoreRef: -+ name: vault-backend -+ kind: ClusterSecretStore -+ target: -+ name: azure-us-acm-provision-edge-infra-creds -+ creationPolicy: Owner -+ template: -+ type: Opaque -+ metadata: -+ labels: -+ cluster.open-cluster-management.io/credentials: "" -+ cluster.open-cluster-management.io/type: aws -+ data: -+ cloudName: AzurePublicCloud -+ osServicePrincipal.json: |- -+ {{ .azureOsServicePrincipal | toString }} -+ baseDomain: "blueprints.rhecoeng.com" -+ baseDomainResourceGroupName: "dojo-dns-zones" -+ pullSecret: |- -+ {{ .openshiftPullSecret | toString }} -+ ssh-privatekey: |- -+ {{ .sshPrivateKey | toString }} -+ ssh-publickey: |- -+ {{ .sshPublicKey | toString }} -+ httpProxy: "" -+ httpsProxy: "" -+ noProxy: "" -+ additionalTrustBundle: "" -+--- -+# Source: acm/templates/provision/secrets-common.yaml -+apiVersion: external-secrets.io/v1beta1 -+kind: ExternalSecret -+metadata: -+ name: aws-ap-acm-provision-edge-pull-secret -+spec: -+ data: -+ - secretKey: openshiftPullSecret -+ remoteRef: -+ key: secret/data/hub/openshiftPullSecret -+ property: content -+ refreshInterval: 24h0m0s -+ secretStoreRef: -+ name: vault-backend -+ kind: ClusterSecretStore -+ target: -+ name: aws-ap-acm-provision-edge-pull-secret -+ creationPolicy: Owner -+ template: -+ type: kubernetes.io/dockerconfigjson -+ data: -+ .dockerconfigjson: |- -+ {{ .openshiftPullSecret | toString }} -+--- -+# Source: acm/templates/provision/secrets-common.yaml -+apiVersion: external-secrets.io/v1beta1 -+kind: ExternalSecret -+metadata: -+ name: aws-ap-acm-provision-edge-ssh-private-key -+spec: -+ data: -+ - secretKey: sshPrivateKey -+ remoteRef: -+ key: secret/data/hub/privatekey -+ property: content -+ refreshInterval: 24h0m0s -+ secretStoreRef: -+ name: vault-backend -+ kind: ClusterSecretStore -+ target: -+ name: aws-ap-acm-provision-edge-ssh-private-key -+ creationPolicy: Owner -+ template: -+ type: Opaque -+ data: -+ ssh-privatekey: |- -+ {{ .sshPrivateKey | toString }} -+--- -+# Source: acm/templates/provision/secrets-common.yaml -+apiVersion: external-secrets.io/v1beta1 -+kind: ExternalSecret -+metadata: -+ name: azure-us-acm-provision-edge-pull-secret -+spec: -+ data: -+ - secretKey: openshiftPullSecret -+ remoteRef: -+ key: secret/data/hub/openshiftPullSecret -+ property: content -+ refreshInterval: 24h0m0s -+ secretStoreRef: -+ name: vault-backend -+ kind: ClusterSecretStore -+ target: -+ name: azure-us-acm-provision-edge-pull-secret -+ creationPolicy: Owner -+ template: -+ type: kubernetes.io/dockerconfigjson -+ data: -+ .dockerconfigjson: |- -+ {{ .openshiftPullSecret | toString }} -+--- -+# Source: acm/templates/provision/secrets-common.yaml -+apiVersion: external-secrets.io/v1beta1 -+kind: ExternalSecret -+metadata: -+ name: azure-us-acm-provision-edge-ssh-private-key -+spec: -+ data: -+ - secretKey: sshPrivateKey -+ remoteRef: -+ key: secret/data/hub/privatekey -+ property: content -+ refreshInterval: 24h0m0s -+ secretStoreRef: -+ name: vault-backend -+ kind: ClusterSecretStore -+ target: -+ name: azure-us-acm-provision-edge-ssh-private-key -+ creationPolicy: Owner -+ template: -+ type: Opaque -+ data: -+ ssh-privatekey: |- -+ {{ .sshPrivateKey | toString }} -+--- -+# Source: acm/templates/provision/clusterpool.yaml -+apiVersion: cluster.open-cluster-management.io/v1beta1 -+kind: ManagedClusterSet -+metadata: -+ annotations: -+ cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-edge-broker -+ name: acm-provision-edge -+spec: -+ clusterSelector: -+ selectorType: LegacyClusterSetLabel - --- - # Source: acm/templates/multiclusterhub.yaml - apiVersion: operator.open-cluster-management.io/v1 -@@ -12,6 +392,38 @@ - argocd.argoproj.io/sync-wave: "-1" - spec: {} - --- -+# Source: acm/templates/policies/application-policies.yaml -+apiVersion: policy.open-cluster-management.io/v1 -+kind: PlacementBinding -+metadata: -+ name: acm-edge-placement-binding -+ annotations: -+ argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -+placementRef: -+ name: acm-edge-placement -+ kind: PlacementRule -+ apiGroup: apps.open-cluster-management.io -+subjects: -+ - name: acm-edge-clustergroup-policy -+ kind: Policy -+ apiGroup: policy.open-cluster-management.io -+--- -+# Source: acm/templates/policies/application-policies.yaml -+apiVersion: policy.open-cluster-management.io/v1 -+kind: PlacementBinding -+metadata: -+ name: acm-provision-edge-placement-binding -+ annotations: -+ argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -+placementRef: -+ name: acm-provision-edge-placement -+ kind: PlacementRule -+ apiGroup: apps.open-cluster-management.io -+subjects: -+ - name: acm-provision-edge-clustergroup-policy -+ kind: Policy -+ apiGroup: policy.open-cluster-management.io -+--- - # Source: acm/templates/policies/ocp-gitops-policy.yaml - apiVersion: policy.open-cluster-management.io/v1 - kind: PlacementBinding -@@ -28,6 +440,32 @@ - kind: Policy - apiGroup: policy.open-cluster-management.io - --- -+# Source: acm/templates/policies/application-policies.yaml -+apiVersion: apps.open-cluster-management.io/v1 -+kind: PlacementRule -+metadata: -+ name: acm-edge-placement -+spec: -+ clusterConditions: -+ - status: 'True' -+ type: ManagedClusterConditionAvailable -+ clusterSelector: -+ matchLabels: -+ clusterGroup: acm-region -+--- -+# Source: acm/templates/policies/application-policies.yaml -+apiVersion: apps.open-cluster-management.io/v1 -+kind: PlacementRule -+metadata: -+ name: acm-provision-edge-placement -+spec: -+ clusterConditions: -+ - status: 'True' -+ type: ManagedClusterConditionAvailable -+ clusterSelector: -+ matchLabels: -+ clusterGroup: region -+--- - # Source: acm/templates/policies/ocp-gitops-policy.yaml - apiVersion: apps.open-cluster-management.io/v1 - kind: PlacementRule -@@ -44,6 +482,187 @@ - values: - - OpenShift - --- -+# Source: acm/templates/policies/application-policies.yaml -+# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -+apiVersion: policy.open-cluster-management.io/v1 -+kind: Policy -+metadata: -+ name: acm-edge-clustergroup-policy -+ annotations: -+ argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -+ argocd.argoproj.io/compare-options: IgnoreExtraneous -+spec: -+ remediationAction: enforce -+ disabled: false -+ policy-templates: -+ - objectDefinition: -+ apiVersion: policy.open-cluster-management.io/v1 -+ kind: ConfigurationPolicy -+ metadata: -+ name: acm-edge-clustergroup-config -+ spec: -+ remediationAction: enforce -+ severity: medium -+ namespaceSelector: -+ include: -+ - default -+ object-templates: -+ - complianceType: mustonlyhave -+ objectDefinition: -+ apiVersion: argoproj.io/v1alpha1 -+ kind: Application -+ metadata: -+ name: mypattern-acm-edge -+ namespace: openshift-gitops -+ finalizers: -+ - resources-finalizer.argocd.argoproj.io/foreground -+ spec: -+ project: default -+ source: -+ repoURL: https://github.com/pattern-clone/mypattern -+ targetRevision: main -+ path: common/clustergroup -+ helm: -+ ignoreMissingValueFiles: true -+ valueFiles: -+ - "/values-global.yaml" -+ - "/values-acm-edge.yaml" -+ - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-edge.yaml' -+ # We cannot use $.Values.global.clusterVersion because that gets resolved to the -+ # hub's cluster version, whereas we want to include the spoke cluster version -+ - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-edge.yaml' -+ parameters: -+ - name: global.repoURL -+ value: $ARGOCD_APP_SOURCE_REPO_URL -+ - name: global.targetRevision -+ value: $ARGOCD_APP_SOURCE_TARGET_REVISION -+ - name: global.namespace -+ value: $ARGOCD_APP_NAMESPACE -+ - name: global.pattern -+ value: mypattern -+ - name: global.hubClusterDomain -+ value: apps.hub.example.com -+ - name: global.localClusterDomain -+ value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' -+ # Requires ACM 2.6 or higher -+ - name: global.clusterDomain -+ value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' -+ # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) -+ - name: global.clusterVersion -+ value: '{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}' -+ - name: global.clusterPlatform -+ value: -+ - name: clusterGroup.name -+ value: acm-edge -+ - name: clusterGroup.isHubCluster -+ value: "false" -+ destination: -+ server: https://kubernetes.default.svc -+ namespace: mypattern-acm-edge -+ syncPolicy: -+ automated: -+ prune: false -+ selfHeal: true -+ ignoreDifferences: -+ - group: apps -+ kind: Deployment -+ jsonPointers: -+ - /spec/replicas -+ - group: route.openshift.io -+ kind: Route -+ jsonPointers: -+ - /status -+--- -+# Source: acm/templates/policies/application-policies.yaml -+apiVersion: policy.open-cluster-management.io/v1 -+kind: Policy -+metadata: -+ name: acm-provision-edge-clustergroup-policy -+ annotations: -+ argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -+ argocd.argoproj.io/compare-options: IgnoreExtraneous -+spec: -+ remediationAction: enforce -+ disabled: false -+ policy-templates: -+ - objectDefinition: -+ apiVersion: policy.open-cluster-management.io/v1 -+ kind: ConfigurationPolicy -+ metadata: -+ name: acm-provision-edge-clustergroup-config -+ spec: -+ remediationAction: enforce -+ severity: medium -+ namespaceSelector: -+ include: -+ - default -+ object-templates: -+ - complianceType: mustonlyhave -+ objectDefinition: -+ apiVersion: argoproj.io/v1alpha1 -+ kind: Application -+ metadata: -+ name: mypattern-acm-provision-edge -+ namespace: openshift-gitops -+ finalizers: -+ - resources-finalizer.argocd.argoproj.io/foreground -+ spec: -+ project: default -+ source: -+ repoURL: https://github.com/pattern-clone/mypattern -+ targetRevision: main -+ path: common/clustergroup -+ helm: -+ ignoreMissingValueFiles: true -+ valueFiles: -+ - "/values-global.yaml" -+ - "/values-acm-provision-edge.yaml" -+ - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-edge.yaml' -+ # We cannot use $.Values.global.clusterVersion because that gets resolved to the -+ # hub's cluster version, whereas we want to include the spoke cluster version -+ - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-provision-edge.yaml' -+ parameters: -+ - name: global.repoURL -+ value: $ARGOCD_APP_SOURCE_REPO_URL -+ - name: global.targetRevision -+ value: $ARGOCD_APP_SOURCE_TARGET_REVISION -+ - name: global.namespace -+ value: $ARGOCD_APP_NAMESPACE -+ - name: global.pattern -+ value: mypattern -+ - name: global.hubClusterDomain -+ value: apps.hub.example.com -+ - name: global.localClusterDomain -+ value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' -+ # Requires ACM 2.6 or higher -+ - name: global.clusterDomain -+ value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' -+ # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) -+ - name: global.clusterVersion -+ value: '{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}' -+ - name: global.clusterPlatform -+ value: -+ - name: clusterGroup.name -+ value: acm-provision-edge -+ - name: clusterGroup.isHubCluster -+ value: "false" -+ destination: -+ server: https://kubernetes.default.svc -+ namespace: mypattern-acm-provision-edge -+ syncPolicy: -+ automated: -+ prune: false -+ selfHeal: true -+ ignoreDifferences: -+ - group: apps -+ kind: Deployment -+ jsonPointers: -+ - /spec/replicas -+ - group: route.openshift.io -+ kind: Route -+ jsonPointers: -+ - /status -+--- - # Source: acm/templates/policies/ocp-gitops-policy.yaml - apiVersion: policy.open-cluster-management.io/v1 - kind: Policy diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml deleted file mode 100644 index 12632e63..00000000 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,978 +0,0 @@ ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-factory - name: manuela-stormshift-line-dashboard -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-factory - name: manuela-stormshift-machine-sensor -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-factory - name: manuela-stormshift-messaging -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-factory - name: manuela-factory-ml-workspace -spec: ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: mypattern-factory - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: mypattern-factory - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: mypattern-factory -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-factory - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: - - name: stormshift - path: charts/factory/manuela-stormshift - plugin: - name: helm-with-kustomize - project: factory - - name: odh - namespace: manuela-factory-ml-workspace - path: charts/datacenter/opendatahub - project: factory - argoCD: - configManagementPlugins: - - image: quay.io/hybridcloudpatterns/utility-container:latest - name: helm-with-kustomize - pluginArgs: - - --loglevel=debug - pluginConfig: | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-factory.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern=mypattern - --set global.clusterDomain=region.example.com - --set global.hubClusterDomain=apps.hub.example.com - --set global.localClusterDomain=apps.region.example.com - --set clusterGroup.name=factory - --post-renderer ./kustomize"] - initContainers: [] - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - resourceHealthChecks: - - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - kind: PersistentVolumeClaim - resourceTrackingMethod: label - imperative: - activeDeadlineSeconds: 3600 - adminClusterRoleName: imperative-admin-cluster-role - adminServiceAccountCreate: true - adminServiceAccountName: imperative-admin-sa - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: - - name: test - playbook: ansible/test.yml - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: false - managedClusterGroups: {} - name: factory - namespaces: - - manuela-stormshift-line-dashboard - - manuela-stormshift-machine-sensor - - manuela-stormshift-messaging - - manuela-factory-ml-workspace - nodes: [] - operatorgroupExcludes: - - manuela-factory-ml-workspace - projects: - - factory - sharedValueFiles: [] - subscriptions: - - channel: stable - name: opendatahub-operator - source: community-operators - - channel: stable - name: seldon-operator - namespace: manuela-stormshift-messaging - source: community-operators - - channel: stable - name: amq-streams - namespace: manuela-stormshift-messaging - - channel: 7.x - name: amq-broker-rhel8 - namespace: manuela-stormshift-messaging - - channel: stable - name: red-hat-camel-k - namespace: manuela-stormshift-messaging - targetCluster: in-cluster - enabled: all - global: - clusterDomain: region.example.com - clusterPlatform: aws - clusterVersion: "4.12" - extraValueFiles: [] - git: - account: hybrid-cloud-patterns - dev_revision: main - email: someone@somewhere.com - hostname: github.com - hubClusterDomain: apps.hub.example.com - localClusterDomain: apps.region.example.com - namespace: pattern-namespace - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Manual - useCSV: true - pattern: mypattern - repoURL: https://github.com/pattern-clone/mypattern - secretStore: - backend: vault - targetRevision: main - main: - clusterGroupName: example - git: - repoURL: https://github.com/pattern-clone/mypattern - revision: main - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: trusted-ca-bundle - namespace: imperative - annotations: - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml -kind: ConfigMap -apiVersion: v1 -metadata: - name: "argocd-cmp-helm-with-kustomize" - namespace: mypattern-factory -data: - "plugin.yaml": | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-factory.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern=mypattern - --set global.clusterDomain=region.example.com - --set global.hubClusterDomain=apps.hub.example.com - --set global.localClusterDomain=apps.region.example.com - --set clusterGroup.name=factory - --post-renderer ./kustomize"] ---- -# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml -kind: ConfigMap -apiVersion: v1 -metadata: - name: trusted-ca-bundle - namespace: mypattern-factory - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-admin-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-admin-clusterrolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-admin-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: mypattern-factory-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: factory-gitops-argocd-application-controller - namespace: mypattern-factory - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: factory-gitops-argocd-server - namespace: mypattern-factory - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: factory-gitops-argocd-dex-server - namespace: mypattern-factory ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/job.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: imperative-cronjob - namespace: imperative -spec: - schedule: "*/10 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: imperative-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: fetch-ca - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; - ls -l /tmp/ca-bundles/ - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - - name: ca-bundles - mountPath: /etc/pki/tls/certs - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - - name: test - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - ansible/test.yml - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-factory - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - name: ca-bundles - emptyDir: {} - restartPolicy: Never ---- -# Source: clustergroup/templates/core/subscriptions.yaml ---- ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: factory - namespace: mypattern-factory -spec: - description: "Pattern factory" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: stormshift - namespace: mypattern-factory - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: mypattern-factory - project: factory - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/factory/manuela-stormshift - plugin: { - "name": "helm-with-kustomize" -} - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: odh - namespace: mypattern-factory - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-factory-ml-workspace - project: factory - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/opendatahub - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-factory.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-factory.yaml" - - "/values-4.12-factory.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: factory-gitops - namespace: mypattern-factory - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - resourceTrackingMethod: label - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - sidecarContainers: - - name: helm-with-kustomize - command: [/var/run/argocd/argocd-cmp-server] - args: [ - "--loglevel=debug" -] - image: quay.io/hybridcloudpatterns/utility-container:latest - imagePullPolicy: Always - securityContext: - runAsNonRoot: true - volumeMounts: - - mountPath: /var/run/argocd - name: var-files - - mountPath: /home/argocd/cmp-server/plugins - name: plugins - - mountPath: /tmp - name: cmp-tmp - - mountPath: /home/argocd/cmp-server/config/plugin.yaml - subPath: plugin.yaml - name: helm-with-kustomize - volumes: - - emptyDir: {} - name: cmp-tmp - - configMap: - name: "argocd-cmp-helm-with-kustomize" - name: helm-with-kustomize - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: factory-gitops-link - namespace: mypattern-factory -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://factory-gitops-server-mypattern-factory.apps.region.example.com' - location: ApplicationMenu - text: 'Factory ArgoCD' ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-stormshift-line-dashboard-operator-group - namespace: manuela-stormshift-line-dashboard -spec: - targetNamespaces: - - manuela-stormshift-line-dashboard ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-stormshift-machine-sensor-operator-group - namespace: manuela-stormshift-machine-sensor -spec: - targetNamespaces: - - manuela-stormshift-machine-sensor ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-stormshift-messaging-operator-group - namespace: manuela-stormshift-messaging -spec: - targetNamespaces: - - manuela-stormshift-messaging ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: opendatahub-operator - namespace: openshift-operators -spec: - name: opendatahub-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: seldon-operator - namespace: manuela-stormshift-messaging -spec: - name: seldon-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-streams - namespace: manuela-stormshift-messaging -spec: - name: amq-streams - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-broker-rhel8 - namespace: manuela-stormshift-messaging -spec: - name: amq-broker-rhel8 - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: 7.x - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: red-hat-camel-k - namespace: manuela-stormshift-messaging -spec: - name: red-hat-camel-k - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml deleted file mode 100644 index 89691e7b..00000000 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,1926 +0,0 @@ ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: golang-external-secrets -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: external-secrets -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: open-cluster-management -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: manuela-ml-workspace -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: manuela-tst-all -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: manuela-ci -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: manuela-data-lake -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: staging -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: vault -spec: ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: mypattern-datacenter - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: mypattern-datacenter - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: mypattern-datacenter -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-datacenter - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: - acm: - ignoreDifferences: - - group: internal.open-cluster-management.io - jsonPointers: - - /spec/loggingCA - kind: ManagedClusterInfo - name: acm - namespace: open-cluster-management - path: common/acm - project: datacenter - odh: - name: odh - namespace: manuela-ml-workspace - path: charts/datacenter/opendatahub - project: datacenter - pipelines: - name: pipelines - namespace: manuela-ci - path: charts/datacenter/pipelines - project: datacenter - production-data-lake: - ignoreDifferences: - - group: apps - jsonPointers: - - /spec/replicas - kind: Deployment - - group: route.openshift.io - jsonPointers: - - /status - kind: Route - - group: image.openshift.io - jsonPointers: - - /spec/tags - kind: ImageStream - - group: apps.openshift.io - jsonPointers: - - /spec/template/spec/containers/0/image - kind: DeploymentConfig - name: production-data-lake - namespace: manuela-data-lake - path: charts/datacenter/manuela-data-lake - project: production-datalake - secrets: - name: external-secrets - namespace: external-secrets - path: charts/datacenter/external-secrets - project: golang-external-secrets - secrets-operator: - name: golang-external-secrets - namespace: golang-external-secrets - path: common/golang-external-secrets - project: golang-external-secrets - test: - name: manuela-test - namespace: manuela-tst-all - path: charts/datacenter/manuela-tst - plugin: - name: helm-with-kustomize - project: datacenter - vault: - chart: vault - name: vault - namespace: vault - overrides: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: LoadBalancer - - name: server.route.enabled - value: "true" - - name: server.route.host - value: null - - name: server.route.tls.termination - value: edge - - name: server.image.repository - value: registry.connect.redhat.com/hashicorp/vault - - name: server.image.tag - value: 1.10.3-ubi - project: datacenter - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - argoCD: - configManagementPlugins: - - image: quay.io/hybridcloudpatterns/utility-container:latest - name: helm-with-kustomize - pluginArgs: - - --loglevel=debug - pluginConfig: | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-datacenter.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern=mypattern - --set global.clusterDomain=region.example.com - --set global.hubClusterDomain=apps.hub.example.com - --set global.localClusterDomain=apps.region.example.com - --set clusterGroup.name=datacenter - --post-renderer ./kustomize"] - initContainers: [] - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - resourceHealthChecks: - - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - kind: PersistentVolumeClaim - resourceTrackingMethod: label - imperative: - activeDeadlineSeconds: 3600 - adminClusterRoleName: imperative-admin-cluster-role - adminServiceAccountCreate: true - adminServiceAccountName: imperative-admin-sa - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: - - name: test - playbook: ansible/test.yml - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: true - managedClusterGroups: - factory: - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - matchLabels: - clusterGroup: factory - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" - name: factory - name: datacenter - namespaces: - - golang-external-secrets - - external-secrets - - open-cluster-management - - manuela-ml-workspace - - manuela-tst-all - - manuela-ci - - manuela-data-lake - - staging - - vault - nodes: [] - operatorgroupExcludes: - - manuela-ml-workspace - projects: - - datacenter - - production-datalake - - golang-external-secrets - - vault - sharedValueFiles: [] - subscriptions: - acm: - channel: release-2.6 - name: advanced-cluster-management - namespace: open-cluster-management - amqbroker-prod: - channel: 7.x - name: amq-broker-rhel8 - namespace: manuela-tst-all - amqstreams-prod-dev: - channel: stable - name: amq-streams - namespaces: - - manuela-data-lake - - manuela-tst-all - camelk-prod-dev: - channel: stable - name: red-hat-camel-k - namespaces: - - manuela-data-lake - - manuela-tst-all - odh: - channel: stable - name: opendatahub-operator - source: community-operators - pipelines: - channel: latest - name: openshift-pipelines-operator-rh - source: redhat-operators - seldon-prod-dev: - channel: stable - name: seldon-operator - namespaces: - - manuela-ml-workspace - - manuela-tst-all - source: community-operators - targetCluster: in-cluster - enabled: all - global: - clusterDomain: region.example.com - clusterPlatform: aws - clusterVersion: "4.12" - extraValueFiles: [] - git: - account: hybrid-cloud-patterns - dev_revision: main - email: someone@somewhere.com - hostname: github.com - hubClusterDomain: apps.hub.example.com - localClusterDomain: apps.region.example.com - namespace: pattern-namespace - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Manual - useCSV: true - pattern: mypattern - repoURL: https://github.com/pattern-clone/mypattern - secretStore: - backend: vault - targetRevision: main - main: - clusterGroupName: example - git: - repoURL: https://github.com/pattern-clone/mypattern - revision: main - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: trusted-ca-bundle - namespace: imperative - annotations: - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml -kind: ConfigMap -apiVersion: v1 -metadata: - name: "argocd-cmp-helm-with-kustomize" - namespace: mypattern-datacenter -data: - "plugin.yaml": | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-datacenter.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern=mypattern - --set global.clusterDomain=region.example.com - --set global.hubClusterDomain=apps.hub.example.com - --set global.localClusterDomain=apps.region.example.com - --set clusterGroup.name=datacenter - --post-renderer ./kustomize"] ---- -# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml -kind: ConfigMap -apiVersion: v1 -metadata: - name: trusted-ca-bundle - namespace: mypattern-datacenter - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-admin-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-admin-clusterrolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-admin-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: mypattern-datacenter-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: datacenter-gitops-argocd-application-controller - namespace: mypattern-datacenter - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: datacenter-gitops-argocd-server - namespace: mypattern-datacenter - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: datacenter-gitops-argocd-dex-server - namespace: mypattern-datacenter ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/job.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: imperative-cronjob - namespace: imperative -spec: - schedule: "*/10 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: imperative-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: fetch-ca - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; - ls -l /tmp/ca-bundles/ - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - - name: ca-bundles - mountPath: /etc/pki/tls/certs - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - - name: test - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - ansible/test.yml - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-datacenter - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - name: ca-bundles - emptyDir: {} - restartPolicy: Never ---- -# Source: clustergroup/templates/imperative/unsealjob.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: imperative -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: fetch-ca - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; - ls -l /tmp/ca-bundles/ - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - - name: ca-bundles - mountPath: /etc/pki/tls/certs - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - - name: unseal-playbook - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-datacenter - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - name: ca-bundles - emptyDir: {} - restartPolicy: Never ---- -# Source: clustergroup/templates/core/subscriptions.yaml ---- ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: datacenter - namespace: mypattern-datacenter -spec: - description: "Pattern datacenter" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: production-datalake - namespace: mypattern-datacenter -spec: - description: "Pattern production-datalake" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: golang-external-secrets - namespace: mypattern-datacenter -spec: - description: "Pattern golang-external-secrets" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: vault - namespace: mypattern-datacenter -spec: - description: "Pattern vault" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: acm - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: open-cluster-management - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/acm - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - ignoreDifferences: [ - { - "group": "internal.open-cluster-management.io", - "jsonPointers": [ - "/spec/loggingCA" - ], - "kind": "ManagedClusterInfo" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: odh - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-ml-workspace - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/opendatahub - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: pipelines - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-ci - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/pipelines - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: production-data-lake - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-data-lake - project: production-datalake - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/manuela-data-lake - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - ignoreDifferences: [ - { - "group": "apps", - "jsonPointers": [ - "/spec/replicas" - ], - "kind": "Deployment" - }, - { - "group": "route.openshift.io", - "jsonPointers": [ - "/status" - ], - "kind": "Route" - }, - { - "group": "image.openshift.io", - "jsonPointers": [ - "/spec/tags" - ], - "kind": "ImageStream" - }, - { - "group": "apps.openshift.io", - "jsonPointers": [ - "/spec/template/spec/containers/0/image" - ], - "kind": "DeploymentConfig" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: external-secrets - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: external-secrets - project: golang-external-secrets - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/external-secrets - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: golang-external-secrets - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: golang-external-secrets - project: golang-external-secrets - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/golang-external-secrets - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: manuela-test - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-tst-all - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/manuela-tst - plugin: { - "name": "helm-with-kustomize" -} - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: vault - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: vault - project: datacenter - source: - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - chart: vault - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: "LoadBalancer" - - name: server.route.enabled - value: "true" - - name: server.route.host - value: - - name: server.route.tls.termination - value: "edge" - - name: server.image.repository - value: "registry.connect.redhat.com/hashicorp/vault" - - name: server.image.tag - value: "1.10.3-ubi" - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: datacenter-gitops - namespace: mypattern-datacenter - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - resourceTrackingMethod: label - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - sidecarContainers: - - name: helm-with-kustomize - command: [/var/run/argocd/argocd-cmp-server] - args: [ - "--loglevel=debug" -] - image: quay.io/hybridcloudpatterns/utility-container:latest - imagePullPolicy: Always - securityContext: - runAsNonRoot: true - volumeMounts: - - mountPath: /var/run/argocd - name: var-files - - mountPath: /home/argocd/cmp-server/plugins - name: plugins - - mountPath: /tmp - name: cmp-tmp - - mountPath: /home/argocd/cmp-server/config/plugin.yaml - subPath: plugin.yaml - name: helm-with-kustomize - volumes: - - emptyDir: {} - name: cmp-tmp - - configMap: - name: "argocd-cmp-helm-with-kustomize" - name: helm-with-kustomize - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: datacenter-gitops-link - namespace: mypattern-datacenter -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://datacenter-gitops-server-mypattern-datacenter.apps.region.example.com' - location: ApplicationMenu - text: 'Datacenter ArgoCD' ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: golang-external-secrets-operator-group - namespace: golang-external-secrets -spec: - targetNamespaces: - - golang-external-secrets ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: external-secrets-operator-group - namespace: external-secrets -spec: - targetNamespaces: - - external-secrets ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: open-cluster-management-operator-group - namespace: open-cluster-management -spec: - targetNamespaces: - - open-cluster-management ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-tst-all-operator-group - namespace: manuela-tst-all -spec: - targetNamespaces: - - manuela-tst-all ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-ci-operator-group - namespace: manuela-ci -spec: - targetNamespaces: - - manuela-ci ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-data-lake-operator-group - namespace: manuela-data-lake -spec: - targetNamespaces: - - manuela-data-lake ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: staging-operator-group - namespace: staging -spec: - targetNamespaces: - - staging ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: vault-operator-group - namespace: vault -spec: - targetNamespaces: - - vault ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: advanced-cluster-management - namespace: open-cluster-management -spec: - name: advanced-cluster-management - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: release-2.6 - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-broker-rhel8 - namespace: manuela-tst-all -spec: - name: amq-broker-rhel8 - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: 7.x - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-streams - namespace: manuela-data-lake -spec: - name: amq-streams - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-streams - namespace: manuela-tst-all -spec: - name: amq-streams - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: red-hat-camel-k - namespace: manuela-data-lake -spec: - name: red-hat-camel-k - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: red-hat-camel-k - namespace: manuela-tst-all -spec: - name: red-hat-camel-k - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: opendatahub-operator - namespace: openshift-operators -spec: - name: opendatahub-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-pipelines-operator-rh - namespace: openshift-operators -spec: - name: openshift-pipelines-operator-rh - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: latest - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: seldon-operator - namespace: manuela-ml-workspace -spec: - name: seldon-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: seldon-operator - namespace: manuela-tst-all -spec: - name: seldon-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index bc751aea..00000000 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,2073 +0,0 @@ ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: open-cluster-management -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: openshift-serverless -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: opendatahub -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: openshift-storage -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: xraylab-1 -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: knative-serving -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: staging -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: vault -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: golang-external-secrets -spec: ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: mypattern-hub - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: mypattern-hub - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: mypattern-hub -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-hub - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: - golang-external-secrets: - name: golang-external-secrets - namespace: golang-external-secrets - path: common/golang-external-secrets - project: hub - kafdrop: - name: kafdrop - namespace: xraylab-1 - path: charts/all/kafdrop - project: medical-diagnosis - kafka: - name: kafka - namespace: xraylab-1 - path: charts/all/kafka - project: medical-diagnosis - opendatahub: - name: odh - namespace: opendatahub - path: charts/all/opendatahub - project: medical-diagnosis - openshift-data-foundations: - name: odf - namespace: openshift-storage - path: charts/all/openshift-data-foundations - project: medical-diagnosis - openshift-serverless: - name: serverless - namespace: xraylab-1 - path: charts/all/openshift-serverless - project: medical-diagnosis - service-account: - name: xraylab-service-account - namespace: xraylab-1 - path: charts/all/medical-diagnosis/service-account - project: medical-diagnosis - vault: - chart: vault - name: vault - namespace: vault - overrides: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: LoadBalancer - - name: server.route.enabled - value: "true" - - name: server.route.host - value: null - - name: server.route.tls.termination - value: edge - - name: server.image.repository - value: registry.connect.redhat.com/hashicorp/vault - - name: server.image.tag - value: 1.10.3-ubi - project: hub - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - xraylab-database: - name: xraylab-database - namespace: xraylab-1 - path: charts/all/medical-diagnosis/database - project: medical-diagnosis - xraylab-grafana-dashboards: - name: xraylab-grafana-dashboards - namespace: xraylab-1 - path: charts/all/medical-diagnosis/grafana - project: medical-diagnosis - xraylab-image-generator: - ignoreDifferences: - - group: apps.openshift.io - jqPathExpressions: - - .spec.template.spec.containers[].image - kind: DeploymentConfig - name: xraylab-image-generator - namespace: xraylab-1 - path: charts/all/medical-diagnosis/image-generator - project: medical-diagnosis - xraylab-image-server: - ignoreDifferences: - - group: apps.openshift.io - jqPathExpressions: - - .spec.template.spec.containers[].image - kind: DeploymentConfig - name: xraylab-image-server - namespace: xraylab-1 - path: charts/all/medical-diagnosis/image-server - project: medical-diagnosis - xraylab-init: - name: xraylab-init - namespace: xraylab-1 - path: charts/all/medical-diagnosis/xray-init - project: medical-diagnosis - argoCD: - configManagementPlugins: [] - initContainers: [] - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - resourceHealthChecks: - - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - kind: PersistentVolumeClaim - resourceTrackingMethod: label - imperative: - activeDeadlineSeconds: 3600 - adminClusterRoleName: imperative-admin-cluster-role - adminServiceAccountCreate: true - adminServiceAccountName: imperative-admin-sa - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: - - name: test - playbook: ansible/test.yml - timeout: 234 - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: true - managedClusterGroups: - region-one: - clusterSelector: - matchLabels: - clusterGroup: region-one - helmOverrides: - - name: clusterGroup.isHubCluster - value: false - name: region-one - name: hub - namespaces: - - open-cluster-management - - openshift-serverless - - opendatahub - - openshift-storage - - xraylab-1 - - knative-serving - - staging - - vault - - golang-external-secrets - nodes: [] - projects: - - hub - - medical-diagnosis - sharedValueFiles: [] - subscriptions: - amq-streams: - channel: stable - name: amq-streams - namespace: xraylab-1 - grafana: - channel: v4 - name: grafana-operator - namespace: xraylab-1 - source: community-operators - odf: - channel: stable-4.11 - name: odf-operator - namespace: openshift-storage - opendatahub: - name: opendatahub-operator - source: community-operators - severless: - channel: stable - name: serverless-operator - targetCluster: in-cluster - enabled: all - global: - clusterDomain: region.example.com - clusterPlatform: aws - clusterVersion: "4.12" - extraValueFiles: [] - git: - account: hybrid-cloud-patterns - dev_revision: main - email: someone@somewhere.com - hostname: github.com - hubClusterDomain: apps.hub.example.com - localClusterDomain: apps.region.example.com - namespace: pattern-namespace - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Manual - useCSV: true - pattern: mypattern - repoURL: https://github.com/pattern-clone/mypattern - secretStore: - backend: vault - targetRevision: main - main: - clusterGroupName: example - git: - repoURL: https://github.com/pattern-clone/mypattern - revision: main - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: trusted-ca-bundle - namespace: imperative - annotations: - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml -kind: ConfigMap -apiVersion: v1 -metadata: - name: trusted-ca-bundle - namespace: mypattern-hub - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-admin-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-admin-clusterrolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-admin-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: mypattern-hub-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: hub-gitops-argocd-application-controller - namespace: mypattern-hub - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: hub-gitops-argocd-server - namespace: mypattern-hub - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: hub-gitops-argocd-dex-server - namespace: mypattern-hub ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/job.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: imperative-cronjob - namespace: imperative -spec: - schedule: "*/10 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: imperative-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: fetch-ca - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; - ls -l /tmp/ca-bundles/ - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - - name: ca-bundles - mountPath: /etc/pki/tls/certs - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - - name: test - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "234" - - ansible-playbook - - -e - - "@/values/values.yaml" - - ansible/test.yml - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-hub - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - name: ca-bundles - emptyDir: {} - restartPolicy: Never ---- -# Source: clustergroup/templates/imperative/unsealjob.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: imperative -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: fetch-ca - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; - ls -l /tmp/ca-bundles/ - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - - name: ca-bundles - mountPath: /etc/pki/tls/certs - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - - name: unseal-playbook - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-hub - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - name: ca-bundles - emptyDir: {} - restartPolicy: Never ---- -# Source: clustergroup/templates/core/subscriptions.yaml ---- ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: hub - namespace: mypattern-hub -spec: - description: "Pattern hub" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: medical-diagnosis - namespace: mypattern-hub -spec: - description: "Pattern medical-diagnosis" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: golang-external-secrets - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: golang-external-secrets - project: hub - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/golang-external-secrets - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: kafdrop - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/kafdrop - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: kafka - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/kafka - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: odh - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: opendatahub - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/opendatahub - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: odf - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: openshift-storage - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/openshift-data-foundations - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: serverless - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/openshift-serverless - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-service-account - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/service-account - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: vault - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: vault - project: hub - source: - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - chart: vault - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: "LoadBalancer" - - name: server.route.enabled - value: "true" - - name: server.route.host - value: - - name: server.route.tls.termination - value: "edge" - - name: server.image.repository - value: "registry.connect.redhat.com/hashicorp/vault" - - name: server.image.tag - value: "1.10.3-ubi" - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-database - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/database - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-grafana-dashboards - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/grafana - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-image-generator - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/image-generator - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - ignoreDifferences: [ - { - "group": "apps.openshift.io", - "jqPathExpressions": [ - ".spec.template.spec.containers[].image" - ], - "kind": "DeploymentConfig" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-image-server - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/image-server - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - ignoreDifferences: [ - { - "group": "apps.openshift.io", - "jqPathExpressions": [ - ".spec.template.spec.containers[].image" - ], - "kind": "DeploymentConfig" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-init - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/xray-init - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: hub-gitops - namespace: mypattern-hub - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - resourceTrackingMethod: label - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: hub-gitops-link - namespace: mypattern-hub -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQwAAAEMCAYAAAAxjIiTAABtCklEQVR4nOy9B5gkx30f+qvqMHHj5RwA3OGAQwaIQ86JYBJFUgyiRJHm06Msy7QtPkkkre9ZFml9T5ItW6YtySZNijkiA0Q85EM6AAfgIu4Ol/Pepokd6v++qu7Zm9udmZ3QPTML9I/fcHE7O9011VW/+uc/R4QIESLUiYgwIkSIUDciwogQIULdiAgjQoQIdSMijAgRItSNiDAiRIhQNyLCiBAhQt2ICCNChAh1IyKMCBEi1I2IMCJEiFA3IsKIECFC3YgII0KECHUjIowIESLUjYgwIkSIUDciwogQIULdiAgjQoQIdSMijAgRItSNiDAiRIhQNyLCiBAhQt2ICCNChAh1IyKMCBEi1I2IMCJEiFA3IsKIECFC3YgII0KECHUjIowIESLUjYgwIkSIUDciwogQIULdiAgjQoQIdSMijAgRItSNiDAiRIhQNyLCiBAhQt2ICCNChAh1IyKMCBEi1I2IMCJEiFA39E4PIEK4uPduQnzVCDRiIOIQjMDAAJA6LggAo1M/S2AT/1cGOvU7kv8jBsbkdcn7tfw3995jROqCrutgDWZj6XmTLxZhJiJ6iu8y/HDDBswaOBu6yyH3rEtFMIfDYRx6UWeWUdQ1xnXOSbc1YRK0mO5S3AXFGbEYgBgHmRzQAGYAjHk8IWmBbDDmcIIlOCxBKALIOy4VdWIFMGZpGhwXwo05wnE0jbjG4QoHBo/B4QyCGI4sjuPz/UanpypCE4gIYwbiVy8dgx5jSHAd4Jp39MsnKQg3n9uHe986Eou5RpoIAwAGGKPZAJtHDHMBzGHALACDYOgjIA1CEkCcATFf6tT8taFNrBBP+nDlXbyf5BCYJAz5yjJgnAijjGEYwBBAxwCoFyMcJ2LDNuMjNljmxl0566U1aUlC4IqK5OUZNMHw/No0vs6iZdmtiJ7MDMJTb2dgFQVcYSNl6Bgby2lIxOIQop8YLdQJywWjlYyxFYywRJKEJAwAvQBS8AihXXYrt0QmAMYAnARwlED7wPg7JGi3YLSHEzukA2OOqxeEbglT0lA8DodiuOPcmBRw2jTcCPUgehpdigf3ONCzOXW0M9/kQKKgua4+QKDFYOIMRmwNY2wNAWcxYCGAPikpzADblA2gANAIAztAwE4CthBhK4F2c7BDI+gdXkCjwjYNtUiZYMi6PfjQhZGdvpOICKOL8K1rCCv+5zg0JsCtIrJunMMspHXwxZpgaxnDxWA4D4QzAMwH0FOvxEAT/zcJPhlVOsjLf0cVPktlRtAp12YNLy5BwCgDDoNhFwibiOg1AbxlAIfZsMiwOZwcMlEQWXzkgoWNXT1CIIgIo8NY/04WTtZWOjyLWRgb1vV4zJnHGFvNCJcBeB8DzgOwAFC2hmkJopwc5KbncvMyBo0zcM6gaVD/Xfr3xEv9redDUWThf04yA/meFPWTSO1uVxCEfBHBdcn/t/d7+SLh/V052TSgYbieOkMHQXgTjL8gBNsoSOw4kjlwfNnslS6Ts+YCKZ7EunMjI2o7EBFGh3DXGwWktDzcvAOXyNC4NodrdCEB14DhcgCrAWWkrKpeTGxE/zSXm13TGHSNwdA5TIPB1Dl0Xf6OeyShMfV3vJwQGtvI/s1PCRUlEpE/FXkowgAcR8BxBWybYDkCtnrRBNFMJrZpINWYIwC2AdgggGeInDdN2zhRSFpukhKw+lO4Y3FEHGEiIow24tEdeTDHUv/99F6NXbEwNw9g5zGwGwi4lgFrAPTXkiKITkkNmiZJgSMmX6b3U/5b88mBsSobkSprJ0Gg0v3IlzIkSSgCcQSKNqFouSjaApYticUnkSrq0SS4BJxkwGYQnmSMnmYCb26+cPbQeZtHldGHx5K48cyIPIJGRBhtwN07c0gWbMSdHPIsnnTJWa0x3CjAbmHA+QDmVSKJiRPYJwgpNUhSSMQ0xGOa+m/5u5I6MRFUFRYbBICJgDCftCRJeAQiUCy6yBddFCyPVMrVmRokIlWXwwBeg8CjxOkJAtut28U8j/cgbzn44MWDbft+73ZEhBESHt6TBc/YKtrxNV2wtTlawDitA9idDLgOwBIAZqXPlk5ZqVoogojrSMY1xM1TBMHKjI1dzA91ofy7SJVGqi1S+sgVXOSKLoqWUOqNmF76KALYA+AJIjwAwV65/aLBo49uHlVLXaTjuH15rC3f6d2KiDBCwBM7crDzOeRhGRqMFTqx2xjwQTBcDC9o6jSUJIkSSUgJIp3QkfBJQqoYvu3xPYPS93UFKZUll3eQlQRScOA4njEVtSWPYwBeIsHuFZweExb2mZrraskUbj473b4v8i5DRBgB4bHNNohyakZtx4mD03ncxYfA6AMAO9uPjzgNJa/kBEkkdaQTGkxDUzaIctH9vYwSKQifPLJ5F5m8g3zBVcbUaeweOYA2E9jdBHrAFWJr3IxbBEImlsRHz6wo5EWogogwAsBj2/JwrTG4jpEApws46BNgeD+g4iVO83KUpAlJCPEYR48kiaShJImSqvFekiQaRYkYlORhCUUc41lH2T7c2kZTm4BtINxPhF/mdXpzrk2WlUzipkjiqBsRYTSJB3cRYoVxCBAKtpvQiS5mjD5JDB9gwNLJRszSQjZ1jlRSQ2/KUHYJ/T2obgSFUgSsI0hJG2NZWxGIJBJRfXG7AHYR4W4CfkEkNsWMmEXE4FAP7jg/2hK1EM1OE3jknTzY6CgsGAYHzuMcnyGiDwFYWYkoOAdipoa+lI6e1ClpIiKJ4CDJQwjAsl2M5xyMZmwUVN4NVZM4JHHsIKJfMmI/Fba2VY/ZLtPjuOXc3raPf6YgIowG8MiOLLjtYtR0eCpLq8DokwB+C8BZfobnBCQZaBpDMqahP20gndKVhyOSJsLFhNThEjI5GyMZB9mCo/5dZbE7ALaA8EMi9suhkeHd8+bMI8OI4frVkX1jMiLCqBNPbilini2wV+TmgdNHAfwugIsmu0ZLRJGKaxjoMZBK6jA0T+iIeKK9YL6tI5t3MJKxleRRgzgKAF4Ese+Qyx/gsfyQafbjhlXJdg+7qxERRi3QX+DxLV/2KkflKeXq7o0M9EUAN/rp4qf+1CeKdEKfIApdqh2dG30EH566QsotOzxmTUcco0TsEcbwj8TwvK7reUPTcf3qVLuH3ZWICKMGntmcw2ExwvqFeY4g9gUw+gSAReV/o4iCA8mEjsEeQ3k8dC0iim6EJI6SxDE85kkcrlvVxrEHYD9yGL5jFrHb6EnSDWcn2j7mbkNEGBWwfnsWju2gAGvQcNlHGMMfEOHCcjsF+QswGdMw2Gsqr0dEFDMDijiUjcPByTFLeVYEVdwMtlJTQP+DhPaAHuNjOo/hvUwcEWFMwtPb8jhycjtPJRZeqHH+hwA+4letOg2mwRVR9KcN9d8RUcw8yMVvuwJjGRtDYzYKRbe8znE5jgP4KZH4h0R2zhZ7MEe3rHlvqigRYfh4ansejmPBtZx+wfFxEP2hKlZTNkdyMemcoS9tYFafqRLAWGTMnPGQz7BoCyVtjIxbsJyK9g1BDK9AiP/quuy+WMIcJ8Zx65qeTgy5Y4gIA8AT2zLoORbDyf7Rc4jwr3xX6YRUUTp1UnENs/pjKjpTiwya7yr4NZSVfWNotKjsG5XVFDpGjP0AwLdu75+1+6mxPK5f+97xpLynCWPDdgsZkYddKCY457cB+AqAdeXBV0RQ4VmDPQYG+0wVqRkRxbsXjEElt0lJY2jMUpmyFWBL7dUV9Demw59gSd2Sf3fnRVM013cd3rOEcf9OQj5zBGnNmAPBvshAXwKwuPR+SapIJ3TMGYipn+/d2XpvIl9wcWKkqELO3cpG0V1E+G+c0fc1XR9maQM3LXt356W8J0swP7k1i/s0oBfG+RD4zwz0tclkYWgMcwdjWDIvoVSQiCzee0gmNCyam8D82XFVl6SCZHkGY/iPBPZXdtE96++W3oXHt+c7MdS24T23DZ7cnsdQLq8nubgJwNcZcMXksO5kXMNcKVUkDVXJKmwVRHUM4gx+SyK4ROpEi9A9yOUdHBspqszYCpAqynqN2DfGdPZsWmPitjXvTvXkPUMYv9i4FX2xhXBdN80gPkOeveKM0vvkb9r+Hh1z+mOIGVpbbBUGZ0jpDDGNqS5gEg4R8i4h51eZaiem5rlMdTS+F3sLMVXnhDA0UlS2jSqRolsE6BuWW7wrFU/nIdK4ZW23t4hpDO+JR//jLW9gCT8PY7mTc7km/iXA/gDA7NL7ckuYOlNEMdBrqkzSdkCSRb/J1c9KkIQxZgdDGl6LgFK7gFL5f1Jp4Or3pWK901XsUXV9/ALD8KqO89JPvwp56ffvxsUl52gsY+HocFHVHq3Qr/oQIP6rzdg/9SXNkevO7OvQSMPBu/GZnoaHdo1jtZXGlvzRlZqmf40Bn/T7e0xAqiDzBj0VpF2Qm6vf1BDXqj8CuW/HLYGMU9FSXxXC7xvi/SSl4oiJl0cQCDh+pPQtSsThtTJg0Bib+O/S798NyBddHDtZwFhlFWUMDN9hTPtbztiBmBHDtavfHdGh746nVwWP7y7ixsdM/PryoQsY2P8L0J3yYJ/4Awb0pQxFFnGzPSpICTHOMBDTMJ0wU3QJw5ZbVcooSQ6SFBzVD0Qo+4dQ0gR1hQuY+VKJRyBS9eMqAE6SyUyVROR3smyB48NFlZci53/S9yiA6BfE6D/kkNuZzC3BHVdonRpuYJiJz6ouPLZtDBaBk128QiP2DQDXln9fqXbM6jOVGqLr7S9mk9I5+szpnVRyIZ4sCthljCHKCMIRXpEY0SXkUC9KjZcUcZQRyEySQJj/LIZGLUUczlRLtQvCr4m0P7/9wnWvPrzjddw+wyWNmfN0GsCj28cwUjjJepC+GcBfAqrloPquKhBLZ8oLMthnqgXaiY3WCGEMFV0labg+QdjilIrxbkFJbTG4JBGPQGYKeXh2DRtHTxZQsKfYNaQ++bQQ2p/tjw2/uNSZTXecP3Mres2MJ9IAntyWw2hhVDdIu4Nz/k0Aa8vfjxkc82fF0ZvubFesmMYwYE6vkuRdgcNZGwXXPdVe8F2OkpvZ4Fy9tBlCHtm8gyNDBVV3o4Ix9GUC/mxkvLh+4ax+cf0MTV7r/qfQAJ7cmkMxm9dIFx8Gk5IFW1N6T260ZExTZJFOdt7VJYlCEkZsGqPn0ZyN43mrrWPrJqg2DJI4NA7TJ49uBfONoYeHCip1vgJeg8CfuIX842Zvn5iJtUO7d/YbxFPbcsjncgZxfIQxSMnizNJ7pEK8NSyYlVAekW45pSVZSLVEr3J6jsrFlyueZr94L0NKGaZPHgZnE42kuwle5quLI0NFVYi4At4gwp8ULfuRVH9a3LJqZmW7dt+MN4GHNmdg5jLcNrTfAGP/yS/KOwEpUSycHW+bJ6QkUnM/A9KpYWvQGZDQGRI6h+Y/DkkQY7aDE3kHtmjMpfpeQEnqiGkeeXSjumI7QqknI+MVSWMTCXxlXIw+tii5lK5aM3OaRnffTDeIJ3YUMDw6qqdM/f0A/TWAVeXv96Z0LFC5AO2O3OQTVvS8S8jY4rT7u0SwXIGi6yoRSP697ovbRVeo92r01ogwQcwecZhdRhxecR7C0aEChsetSl64112Irww4vY8X0kQ3zhDvSffMcBN4/u1R7M/FWS/GbmVgfzPZwNmb1pUaUiVxKFDIvZ7UOZI6m6JilAdgiTKicMpUjfLxzeiH0iHoXUocjksqwOvkqDVlDRLwEhG+nEmmNgwIC7ec3f1Rod0zsw3ivjfzGGAnWEYkrgaxvwPo4vL3lWQxJ4FYyPUrmG+LSOm8pgHTEqS8HTnHOY0oIgQLSRxxnzi6wcbBfNKQksbJsamkAeAZIvZvDE3bWDQ03Hl2d9s0Zmx6+4p5Qxh3kxeB8JcAXVT6vXwgvUmphoRPFpIfegyuQrxrkUUJUqqIDJjhwhECWdtBxnaUJNfp2VZJjRrD3Flx9PdWbIx0FWP0F7ZwzlrT/uE1jM5TcIO4fwfBdEZRKNpnmlxKFqrpsReUBaAnoWPRnLhqTRjmYpEEIcnCrNPNl7UF9o0XahpAIwQLKWDENE299A67Y0s2jcMn8pUMoS4BPyMSfxoz4vs2bn8e/89Hb+/MQKfBjJMw4sUhFB1nvs7xNQC3lpNFKq55Bs4QyUKuu7QvVdRLFlKoGLWciCzaDDndBcdFxrLVT+rg/KsC0hrzggZTU7wiUj79DQ3831lFZ+Cy867szCDrwIwijPXbx2A51KMR/i0H+2R5IlnC5IosErHwyMLgDH2mpiSLOjQQhaJLOJKzMFys6F6L0Aa4RJ6aIkm7w25qU+dYMCum4oImrdM4Mfwe4+L/zhdyyce2jXVqiDUxYwjjV5sc2IWsyTn9Dge+ICcY/ikiH4Jk7mRcD40s4ppXuyKh1ZddqZLGCg72ZQoYKthtL4QTYSosITBuOcg7TsekDXlXKQHPnx1HMsYnu1t7wPBH3NV/czw7zp/a3X3l/mYEYTz9dg5HR10moL8f4F8BMFh6T9cZ5s2KoWeqmBcIVCFgXwWpVuhmMrKOwIGMhUO5IvIN1rKIEC4EEXK2q4yinZI2vDQF3+U/NQFxPoCvxrl5neMW2XO7u0vSmBGEcfL4OFb2jl0AsD8DsKz0e8a8Kll96XDa8ku1o9fkSgWphyscQTiet3FgvKhsFlS50nSELoDlCqWiFN3OkUYqqataLNrkFpsMqxljXyvm7NUjue6KAu16wli/PYdESltCjH3NT1OfwGCv14EsDHe77tsrUjqva9PnHIGDWQtHcxaKYmrptpkJVvZ690HZNiwbOdvpWKkAedjJQ2/SgST13usZ8BVOuVlP7Mh2ZGyV0NWE8cTWHEat8QQBvw/gzvKV25P0+oWEkb1o+rU2a5XPK0EVUCk42J/xpYqZsr0ky3IO4pp6Qb04qMS+RGDkggnHe5HwzkVV+YZ7f6/ppz7L+IysDiyfV95xlVHU7YChSS5feegN9FTynLCPw6XPZfPZ2DO7c20fWyV07RN+9BULNh/XOKdPgOHvAMyF/4ATpobFcxOqb0TQB0NMY+g1qhfmLYflqyAjRadSibbugqqTJ0VfpjY/s4vghSx4bhxabhQ8NwYtPw5eyIAV8kCxAOY4YK6jVjVxHWSYICMGiifhJnogUr3eK9kLN9kDMpMg3fDvQX4J8plj7ZVSZVLXVUJbOyHXjWULHDiWVy0aJ/HuXgH8YSqtP0DjBl1/YWfraHS+MEQVaEszEAfpAmL4tyWygO/LnjsY89LUA16LUqLorZFuXo6sI3AsZyFju+rf3UcWzDu+5E/hKnLQxk7AGDoI4/h+GEOHoY0PgWdHwYs5RSBMJcIJ+BWEQVK/91V8mnxdKY1IcjDjoEQabk8/nIG5cGYvhj13CZxZC+Gm+xXBqM8oAuluA7AjSBlDk6Qhprev/qaqWm9wZc+wHKEaQ5etp2Uc+OPMeHE7UrG32zaoKui+dQ5g/bY88vn8bM7dvwPYp0vjlPt47kAMcwbigUu/CUUW2rTxFaTqVDg4mreVwazrJlBJEhxwbejjJ2Ec24fYwR0wDu/ySCI/Dji22rxe53lWmt2pKoXa45I4PAI5/T0q+0meRCElGE1TJOL2DcKZtxTFxWfBXngm7DmLIeJpb2ySOLo4iE3OQkLXEde1tmpZ8lYnxywcPlGYrB5JXfcfXcG/lk6lR69bHY6Rv94xdhWefyGH8WTRcMn9EvfqcapsHDl9/WkDC+cklJQRJBK6VEOmJ4uSvUKqIU5XqSDeiS83olQtzMO7EH/nDcQObId+8ognQRB59gnWhBGTCMIh1N2OzVdHpAJEmg7R0wd7/jIUl5+D4srzYc9aBDITXS11yBmShJFQpNG+Jy2El6h2YnRKlbUhAP8uyXq+f+35sY5NWveseR8/y55A7w52LTj9r/LaFjGTY+m8JBIBqyL1ShZSXD2Wt3Gy6AVhdcfE+UTh2jCGDiG++3Ukdm6EeXQfWCHnbdgAjZHk+GpKo/OvvEakpA/RO4DisjUonH0ZikvXwO0Z9HsldCdxxDWOhKG3LWVe2TMcgf1Hc8jkJ9cGZa8R4fPxROr1G1bH2zKeSuPrGjy2Iw9nPDuHdPwPBvxmaXycM1Uxa6Bytl/TiGue63Q6srBcUu7Skhek8/CIgjk2jON7kNyyAfGdr8EYPgK4TqgeC6mekNMEaUxcQChpRySSsBedgfy565A/6xK4fXO897uwwlhM40i2mTTGczb2H82rhLWyu7pE+A4Y+xPu9A3fdkn7TZBdQxgP7RiFm3cNjdw/YEz1EZkwBw/2mipPJMgWhjEV6j09WRRdgUPZU8bNjkMShevCOLoHqc1PI7H9ZWhjJ70TmvP2PFIhVZRTBtGmoNy2Qnle7IXLkDv/WuTPfh/c3tkTKk03od2kIXFsuICjJ4uTyXmYiP3b/HD8n5ckkuKyde3dwl3jJel3NIwy6yKA/YsSWSgXaoxjdr8XbxHUEjK55zqdjiwKqsR/l5AF81x9+vARpN58CsnNz0EfPubHRkiJoo1dtTgD17ln12g2doExkByz68DYuxN9h/ciseVFZC+5GfmzLgbF07600R3E4UWEOm0jDXmHwR4TubyrXK1lGGCMvpTsL7ywb3B4W+gDqTCujmP9tjwK1ngfU5Wz2O+WxiVJYuGcOPp7glNFvIzT6etY5B2fLJypPSbaDs7BCzkktr+I9MZHYB7d420m3uG4Oylp2AFJAyWJI55E/uyLkHnf+2EtPMsLCusi+0Y7JQ15i0zOUfYMyzlNNZGz/vfksD/n6b7s7avbd+53hYRRyKlONXeAsQ+U17foTeuVagc0jVKFrGnJQkoWOQvZTpOF79Ewj7yD9MsPIrnjZWXMLEVldhzysRnwSaPFa5UkjmIByU3PwzywC9nLbkH2ghtVcFi32DaUK525SLbBeyJ5OJXQlUquVJNTkJviE0Lnj99h/4cHQx3EJHT88Hx6SxY5O7cSxL4Nhuvhk0Xc4Fg6PxlYfQv5RXtVbkjtr1wos1l0liw4mJ1HcusL6HnxfhgnDlSOlegCtGwIrQThAoaJwqoLkbn6Iygu8h1mXWLbSCiXq96Wx2FX9ZrgPpf4F1OJ2NHrV7cnArTjx5Rj2TojfAIMV5R+JwWAwT4T8QCL4aT8it61YLmEI1kL2U6TBecqCrPvqZ+i/7F/hnH8QFfnajCNgekBLyUpRTkOEltexsA9/xPJN59SXqGSLafTKDiual/ZDpg6x6y+WKUyg9drTHyk4Ii2TUpHV+AT28Zh5YsXg+EHYFA1UEtFfJfMS6q03yCQ8N2ntTQRW1X19lynHQXnMA+9jb5nfo747jc9/b1LNsl0IFt4UaEBgwkXIplG9n23YHzdByFSfV2hokj+Thm6qhkaNogIh44XMDRmTd60LzKw3zNjia03nJ0MfRwdW4m/fJtg5wopMPZZsFMBWpJFZ/WZgUVzGpypAji1yMIlLyiro2ThSw/xna9i8KH/jfjOTac8IDMESsoIIXuYuAaWzyL93P3of+R7KnpVSSAdhtSO8rYLuw01NThjSuo2p/bYuUiAPmHbblsKZ3RsNV6YewmuhnVg9FEAE0+/L22o1oZBnFMlI2etzFP50E8UnM7W3GRegljqracx+PC3YRx5p30xFUGCyX3Mwhm2JE7HRfL1Z9D/4P+CcWR3V5CpPGxyjpetHCa8EANNuVonTa/JgE8JUTz/8e2FUMeAThHGl39F2MrOTDOw3wawBKWMPZ1joNcILEArqU9f02LEcjCU72DNTcZUCnl60xPoW/8jaCMnuuL0bBoaAwurpL+fnh/fsQkDD34b5sEdXTFXjiBVhCdse6yc1f4ew3MEnH6vM0D4tGNZoeskHSGM//IbDIz0axlwB07lSqKvx1C1DoOY+LjfjawWMrbAsVwHE8lKZPHqI+h76ifQMqPd4S5tEUo1CXFCiXGY72xF/0PfQWz/tq6QNCxXqOLCYUIVEDa4crNOWiY6GH5DuNYlT20Lt3Bw22f6nh153P/a2ACH86mJojjkTcRAjxGII0Bn09stSvkhHSunJ8lCqiGbnkDvc78Cz2ffFWShILWSkIvQENdg7t+Jvoe/q4zE3SBpFF1XEUeYUE6BlFGpQv4yBvoE2SLUrLS2r9DdAtA0+yoGuqW8zkV/rxlIAyJ5wZTBagZneUbOTgZmMfXkk289g75nfgGezzR+SpbnW5RqYKB74hSYFn7MiJI09u1QhlDj2J6OSxpSrc23wZ5h6EzVs51UnpKD4YMFN3/pE9vDK+fX9hk+3y2mOfAJAPPgr++4qaEvHUwQTExjSExzug0XHWW76JhJkTHEd21E77O/AM+ONbXQmWmCz5oFfelS6CvPgL5yJfSly8BnzwYMo/PEwXzSCBnENJh7tqPviR9BHz3WcUnDEYR8yPYM8mvapqaUemCLieFjjm2HZstoa2j4kzuyyOez6xj4zaXfKemix0DMaL3Ohea3MaylimRtFyfyHaxpIUXpg9vR/+RPoI8cb3yBMwbePwBt/nzwZFKKa6e9rQkBkc3CPXoUYni4o3kYkjDIZaGTlzKEbnsVvck+jNzyWa+yVwcJU6olOndVAZ6woGtc7Zts3ik32MstcKdw7R8/sbXw4o1rgtdO2iphOHYuxcA+Wi5dxEyO3lQw0kVSr50nYvtFey3RKSMnhzZ6TAVlGcf2NUUW2ty50JcvB+/p8ats0ekvSSg9PTCWLYc2b15no0NZ+5JoJS8m3ngW6Y0Pe4WLO/i9yY8EDbNRkrxHOmkgMdWWsQKED7mOFUpcRtsI48mtGbgOPw9gt5buK59pX8rwbBctHgimxhRhVIO8/MmCg/FOhX3LjWzl0fvCPYi/82bjBk4i8P5+aAsXgU2ncsj3DB3aggXgAwOdTRHnIcVlTIZcTJaF9IaHkNjxUsfD6F0irwF0iPfQNaYcBZMyZzUwfMh17TMf2xG8x6RthGHbri6I7gSwHGWVkvvSrXtGVIiuzmrWt8jaQpXX69zWYUhueQ6pN5/192+DX9owlMQwLVmUQKT+Vp83H8yIdUxEZ6yNCXOMg4+PoufZu2Ec29txr5NUTSwnvHwTpqQMXdWMmfR4zwTo9iEKXr5ry4w+9vY4HNdezqAIY+JL9CR1xKYGoTSMOGeI11gcjiCcyFtKJemM3YLDPPy2yjplxVzjG0hKFz094KkGdXNJGqkUWE9Pw0MODMqB075ZJ8ZhHNyDnufvbc77FORYVPazG1qDJFIek4qHbhwMH+wtZhY+viVYj0lbZtN2MgycbgJjq0u/U60I00bLA5BrMWnwmntwpOh0Ll1dnnq5cfS89AD0k4ebs+IzBpZMNXdicg6eSnVURGdtjnKXnJrY8hKSW5/veHS9PKyKIWa1ysfak9K9HJPTeekiDXTFz3YEK2SEThgPbBaArc9mjEnpQrl7lMEmoQdS6yKh1TZ0FlypijgtlZ9sFXLhJnZsbH7XMAYuVZFmN73ZwmeDAG9zHQ9JsIUc0i895KkmHY7PKLoiNAOoF/SoVXIc9AvBPvhbZ+YDLZQR+kwuOsoBMi8EnWqkzBlT1bRa7YuqSelCZ1W3oZQETxaczjUcYhz60EGkX39cdRbr2Kbtgliudu9Zqb5rRw4i/epjYE4H597vZ1NwRGiPQX613pQxNcOb4eqi45zzzNbxwO4V+mPcO3DcAJzbTw/U4qr0WKu7WEoXtTJRc46rupR1BCpPxFZJZU25UMtBBGHbzRsuLavzgVzt8paUQxASbz2P2N7NHZcyLBFeGrxSwWJapfahiwDc4tp2YHpJqLP4g82vI8axhIGuLw8D70nqyljTyhqWZJqoUUGrJF3YndoojKsOZMmtG1rfrESgbAZoRhd2XRXI1WnCaGf3sLKbgo+NIv3a46rJdEdjM8iLzQjrMWgaU1LGpPPTAMNNlmDzz3j404HcJ1TCOG7tBQO/sryDmfxiPQEEasWnkS7GbbdzMRdgSgVJvfEktNETrZ9ujEGMj0NkGlz08nOZDEQmOJG0abDOkAaBIbbrTcR3vd7x2AxHCFgh2jKk1G6apxfYYcD5DtkX7bz8h4HcJ1TCWK1fkRYkbpzoM0JAMqap3JEwpQuXCMMFO/QkoKpQbtSdwS5Sx4F79AhIqhf1XJMxkGWrEHHU+5mw0YkhSNUwl0PyzadV39lOu1mLUuILaV2aBlfOhEmYxRi/4b59I4FEfoY2e49uHQe5fCUYu3yi5aGvjrRq7IxNJ11YAlmng2nrdhHJzc9CywwHt0CltDA6Cmf/flBxGiNeiSwOHoAYHekOsgBCKd9XD5SUsWerb8vosJThChUPFAbkV0sn9cnFghlj7FounIXffeNoy/cIjTC0jJAXv4wBKzARrdy6sVNOSlyr7hmRUsWIFX6KcVUwDuPEftU9PQyIoRNw9rwDMTICKCOa77IsvYRQJOG8sxvuieMdt12chk7t1ZKUsfUFMKvQ8TwTy3VVUd8wLi4l+Jg52T5IZ3JiF//ueXNbvkVo2arFJJKw6TqAJUq/S8YrfZnGYPLatS6ytuhsmwASSLz9CvSRAGwXVSDJgjIZsFQaLJ1Wqe4KtgWRyUJkM4Btd/w0nQxJ88Q64+ZV1ar2bIF5ZBeKS88FqHPtL20pZWik8p+ChPyOujyU4zqy+dO+Xy9n7Lr73hp+UG7NVu4RGmFoYEsEY5eW/q3yPRK6qtfZLGEwv/ReNb6Qkt6oL110LBt1/IRnu1DtAUJK1ZQqhzylpLoxNuoTg999zM9Y7TayUGA+aXSCMRgHGxtB/O1XvaZI6tl0RvoqSRmGxgNfp15+iYahMQZxSvXhYHRZgusLAOxp5fqhHIFP73bhOsVLSwV+4VcJSia0lp6RxpkqkFMNeUd0tnEyY6rGpHHiYHuMayVSoLJWhd1IFOXoZLa9KxDf/Qb0saGO2VNKsAXBDcFjoroGmpoqeTlpq61ybPuc9Ttaq44fyqq28rkYgzJ2eqHgfmCJqU/5Eg0hxr16ndUwZjmdSzDzjZ3xPW+CWZ2NLOxasM4SBjEO/fgh5cHqdJKJIAqt/qdSSxJTpNtBxvA+x7FaEntDIIx/A5ec+QAuLq97IfWqVrwjnHmxF9VguaTiLjoGvzhO7MCOzo0hQm2oHJOC11HO7WAfGh+WEKG4WOV+S8r9dvqhxRlhHSPqa+XagRPGq4f/QurXZ6heCSVDjMaQiGstkbrOWU1XqlRFrE7ljPgwj7wDbfR4x8XdrkaHp0Z56w7shD5+suPh4kJQaC7WhMlhGKfbC4nhbMspLH9px2tNXzfwGRs6Ns4IJKWL2eoXfguBVr0jMV7d2OkSMGa7Hc1Iheso+wWzrc7viq5Gh+eGMegjx2AcfafjaiP5HpOgKUORosGVLWMS5migC9YfvrDpawdOGLrWm2BgF5V7YOIxTRUtbRaSKGq5UouqiUwHXamMQcuPw5SLMEJ3Q6kleZiHdqv2lJ0mMEeIUArscMZUGMMkTkwQ2MXr+kdjTV83iMGVw4E7D4S1EzdgXjBJK2Sus9rqyLjlqkIlnYIypp085FUBj4yd3Q9XqP61vJjt+PNyicKplcE8R8Mku6H8x1qL89nNXjZQwrh/I8FxrDPBsLD0O01jSsJoBWaN2As54dmQi61OBzk04/h+8EKu4ydW16MLpoekWjJ0GFqmO8LmbSECD8iV1zMNPiUrnIDltmstfviVI01dt6HArce2ZCpHyHmNvDB0jFjfADsXQC/KWiC2ksrOfPtFNRQcrzhJJ9URuLYiDGV574KWfRGmA4M2PgJ9+AjsOUs7PRglHcuDr1bIQDPQ1WHNkS+e2rNM1aWh1UgmXnxs8yjK3xCq+76Om1dVL9JVN2E8usPGtrffxhmL585nhAu9gjjEAeaC0WGH2Ka+3uFxBpyr8vD9QUjpQmshBFbnbHIyzWmQ0kXH8kYUGHgxB334KDoU9Tyj0BVzxJiKlVE1VrsAwldL9IAPG8YYEqaGEXaaCznOGHsf2fYeF1hCRKafnzdsc/5W3iq+88z2vLhmdaLiNesijB/nx5DfUeRnLpp7E4A/BlPl9uKn5EuW0xmeB6cfM2A1lWWnxk3e0iIxeHUvpSSKnK+OdE7CgKpOrY0NoUMhYxGagSuUWgLhdIWeJAmDVEuR4CAFlpjJlR2jzLAqb/FJAn5TaQKnipTYOtGOHvC/LxbyP39wt5V//0pzyjXrIoxF6wWyi+zzwfCfAFxS4U8kHX0QDBcSoGrak6pbwWAaWtPHirIN8OqZqZZLSiXpLBh4bhQ8P9YV+nCEekHQR08oNzgZ8Y7LPVItkZKGFvAaMg2uVBPHpfLlOavCXRKMcCmAv3Qhxk4Qv7vS9eoyep48gwxAfAzAdA7cJQD61X+Rlz8iB9wspGRRyzuSd7xqzJ3cpiowLTMCrtKmOziQCA2BiIGPjyh1shuIXpJF0O5VqanrmmdDbABLBPDZ+Xa2t9KbdV0pZfMUA84pb0JUD+RAJbs1a2KQbFvLEJR3RWeDtXzw7AiY23mf/oxAt0yRVCULWd+12unBeAdPGO5VTWOqbF8jYMAqLjCr0nt1XcmFK/WKxkp8MU8c4i2ESes1ojsdv3R7p8GkGJkdVYVrIswsMKuo7E/dYnuSazpoxUjZMaZp9DUZUjlwBatorqiLMKiJCgbKHdrgQCejljZjuaSSdzr+qEmoRcc6b/uP0BAY4NhKyugWCEHlNSwCQzP7UK+iFoSWfcN9CaNZMNROZS+6osPuVB8kwKzgu2RHCB9SjZTPruOHjg9lxwg8gsszDbRaR7eE8AiDM8/Y0rT9AjW7sRfc4KPjmgETAlwlnDUAKnuJslf579/N6JodKsm+wWcXIsgPFQj6mprGlfEziEuHUqLPS2nnyuDS7Bg1Zb+ovLLkpBb9LL/Orj3mSRiuVf17kletTxKC/KkCZQU7VQR2UhMJlJr+cPKyrzUvC7vdDY27AqUpIubPI5vy3gQm5o7UMegtHao9Z0RgTufrYpTDDSEeQ+OexzLfUjVPD+HU9CQvLLVZg2cphqOaRuIKz4bRNZhM3eQRAzn+T9cnDSr7g1qXK3+/VJ5T88pQcsMvR/luJQ/yCUJ4BDFBEnU+bgI7nTw076dHuJOfE4GJDrXSrAJ5GMrDJMimT560H8z1QisCLAfYrNrk2S+q7wmbSFmUu2fPeCNREoQkCauMJFoF+Xwkr20DoggwHeC657cKq85w2yHJwWXeHIoWn2y5ZCJ8ElFSGoFp5BHJBA91zyqCX8iaQhCdDb01B0QJoRCGHJiuBtjcCJkvYVSD7YpQrMkNQ6kOmlqYciMLX6II1QZBHnG4NsAsjzS4OZOI4/TnSiWicFm48yZO3csjDqFOJdLMrgjcKkFKFyriM2DGkBK//Jqt2jFCkzCmtJ5vAGof1vi4JTpSqP50cA5WyCG+5RWwvYfg5tvfnXxC3bF90jA7XnWufghAuDx8opgMpS5K4uBgLgMfHlLNjcgwuyKWpmT4DKSvoQ91gGveAd5qA6XQJAytBUZjqK3O2D5hdKo6uIR+eC9SzzyI+JsvqQpOje9UqrxRmjjtJGm4cggOoMUaDrFrK1RHBIdD2F6Ryc6BgRxC4vknwLJ5ZK+6De7cRf4AO3schVEYWPO7Bba6b0IiDNZySb5qHhLhE0ZHwJiyqsfeeAHpJ++Ffnh//U2DSgux1GhI08B0Tf30WhySKhlHjuOddOUNieokESlpyI/zGKDFu88wSg7gFuQ4GxzYhEdp8maetPwn5gv1fXnGwLNjSD7/CIy9O5C94UMonnsZSNM7ShphxBcpr6PcWO40nqNpEDhhkL/hW+kCx2tI9yKskmbTgWtg2TGknnsIyeceUQtt2mI5pY2v66qtoTZ7LrR5C6HNmQ/ePwieSoOZMU86IaGaLIvsOMTwENzjR+AeOQT35HFQLgu4rq+rTUPEkncKHrPyRPeoKMLyxlV3h8Iy0mSmCZZMg/f0gvX2gyVT4GbcWyhCQBQLoMw4xPioelE+57WKlJ/nfJrG1d4EGQd2o/eu/4Pc8UPIXXkbRLLXr/nZfpSfK0GBK8Jo/TrBSxjkSRit5JDwGi5VdRC3RpJNDIhDGz2B9CM/Q2Ljs/4xXoMsfEKTpKAvPxPG6rUwVq6GNneBWuxM12ufgEQgxwblMnCPHoK9cxvsHW/B3rsLNDY6MaZakBuUBKAlPK9Kx0CeZ0dKFnXZKuTcyQOjtw/6omXQV5wJfclK6PMXgfcNgMUTgKZPGNSp9BnHARVycCXZHjkAe89OOHt2wj18wCNcTDNnXAPPjCH92F3QTh5H5taPw+2f3RG7hvCTMaoXdmgctaT2RhDKUuJ1HIQ1P19jO7kihPDZmoPRoJ08ip4Hf4T4Gy+eOrUqwV/s2tz5MC98H8yL1sFYvFydjg1BEqZhgvUNgvcNwli1FnTtrbD37ULx1RdgbXoZ4uQJf3zVJ1qpADlAS3aINMgjCkkY05KFlKB0HdrCpTDPvwTm2osVYfDe/pofU+tEcrecr0QSfGC2Iuf4uhsgRk8qkrXeeAXW5tcgho7Xfn7y966LxCtPK7vU+J2fgTtrftslDQrYtVqSVlo5xEsIzejZSuBJre/lBbY0fenGwDi0kRPoeeAHHlmgij3Bf8J8YBZil12F+JU3qcUeiAxYGkq6F+Y5F8FcfT7sq25C4bnHYW3cADE2XFPaUQbRTpBGiSwK0/2d8OZ56QrEL78WsUuuhDZ7futzx7kij5h8nXcJnIN7UXz5GRRefhbi+LHqtiHfUh9/80WVazL24d+BOzivrZIGTQTvBSdhKKm/W+MwJJO1Iv3U+qhSSZq/dP2QCy47hvSjP0f8zZerk4VcSJoOY835SN72YZirzlMnZWjQNBgrVkFfvBzW2ouRf+Qe2G9vmdh4lVDyoijSaFO8hopLmS4UWbhgPX2Ir7se8Wtvhb5wSTiWWk2HvvQMNWfmhZcjv/4hWK++ACoWKhOT/5xjWzeix4xh/IOfhds70D7SULEYwV5yRkgYTVcKn0bCCN1xrxorW0g+/QASG5+pboESAizdg8QN71cvqWO3C1JliV14OYylK5F79B4UnnnMM/ZVOZmleiJ80ggv5dDDtDYLf2HoZ6xG8v0fR2ztxYDeBl8w12CcsQb6ouUorjoXuUfuhnv4YJU58yWNTRsgUmmM3/EpkBlvm/ckhMoY3hJukTPCkTDk4Fr4vtPkC7XlmcXeeAHJDY+pFogVT27XBZ8zD6kPfRKxy68Da8eCrwA+OAepj/w2+Jz5yD/wc4iRk1VVFBX7UAzX5arC16cjC84Ru/gKJD/0SegL21/mn8UTSqLR5i9G9u4fwN6xxX9j0qT46kni5afgzFmA3Lrb/L8JdwFShfSkltGimaCEcM6aFpms1hcLPQRDnkIHdyO9/h7w3HhlshAC2sLF6PnM7yN+1c0dI4sSWCyO5A13Iv1bXwCfPbem6KxUhZASNKVWpOIsqt3edzEnbrgd6c/8fkfI4hQYjFXnoud3/xVil1zhr9cKi0tKm8UCUk/eD3P35kDtUrUQAl8E4qYN5du3ar+oKWGEye6q72YOyWcehH7kQOWT2nWhzVuA9Ce+APP8y8IbS6NgDLHLrkb6Y59Txteqln1qMB6iAVDRU30qv+mTxfV3IPWhT4P39AU/gCagzVuI1G99XhlbFSod7ZxDGz6O1FP3gY8Ptym4Jfh1Xo0TG0FI37w1D3JtwggX8bdeQvytV6raLPjAIFK/+Tswz7805JE0AcYRu+waJD/yabBUT9WjXpKFCLhujEqIq3pNzwYUv/ompcKpsXURtMG5SH/897xnWk0XYBzmzs1IvPKUz7bhRgKFoXZ3r0oyE8E9F2rixcfBivmphEGkRP/ErR9B7KJ1nRplXYivux6JG+8ENKPqylOBXUGVgiCfLKqpIoJgnncJknd+ovGYlDaBz5qrbEH6spWVVTo/LUAShn5kf9tUk25DSN+647mkTSH25osw9+2svBiIVIxF4rrbur5/KtMNJG7+oAqAqmpQEHUGVNUBYXsSRuU3XWiLliH14U9DG2i6aXhboC9ZgeSHP6UidCuSBtegHzuIxManPWP4DEOrmaoIizCoSiJm10IFaA0hsWmDvxAmSRdCQFu0FIlbPgwWT3ZqlA2Bp3uRvO0jyntSzQiqNnqrtgzyCgZVfOBSKosnkLz1g9CXndHijdqD2NpLEb/65uoSBEGprPqRfTNOylCPqEWtpCu/cS2yCUVzZIC5YxP0Q/umGrTkojdjylinL14e6G1HRkawb98+7NmzB8ePH4fjBHtqGSvPRvyam71AskqnC7VuyxCO3560EohUiHzs0qtbu0kFjI6Oqrl7J+i50zQlRRpnrK4iZXgG0PhbL/mG5S5LCa6Fri0C3EJs1XQfDTIhx7sgA8tnEdvyKphdnKpuCAH9jFWIXXplILdzXRevvvYaHnzwQbyycSOOHj2qftff349zzzkHt912G6675lqkewLQ9TlH/PLrYb36Ipw9b1cM8yzVHW0qArSWdKEMxLPU5gtKKpPz9PqmTXjggQfw8iuv4OixY3AdR83dOWvW4NZbbsH111+Pnp7WjKp8cI6K03D27/GiQSfbs4SL2LbXkb/0eriz5rXB1986vPil1scZCmEIOpVt18wQqUbmTUDtFU6BcWXEMva9XcEz4kkX8StuBO9tPYrz2LFj+Id//Ed857vfxf79+yHc0/WBJ9avxw9++CN88AN34it//MdYu3Zty/fUZs9DbN21cPa/U1HKKBUrboYwSjVMq8G84DIVWRkEhoaG1Nx9+zvfwb79+xVRlEPN3Y9+hDvvuEPN3QUXXNDS/WLnX4bCS8/AfmOjV7OkHGrNHFA1NFRy2oyAH27eYopKeDaMkEpiNVBPpk4QzD3boY2PTlVHhIC2ZDnMc6brQT09pNj89X//7/HNv/orJUpzzqEbxukvXcfo2Ci+/8Mf4kv/8l/i1Vdfbfm+ErHzLoM2f2FVW4ba9E0wu5JOKl1SqnG9fYhfdrXK42gVkiy+/ud/jr/85jexZ+9er0BThbkbGxvDD3/8YzV3r7zySkv3ZOleb/ymWeFNpqTR2M63VPe0MBBk1XAEKGGEQhiixeSZWp/lQQTET4ApF6r5zraqVnHz/Es9q3kLKBaL+G9///f43ve/D9u2oU0+scpvKXVkTcOzzz6rNsmhQ4daureENmc+zHMvqvp+1Y0/DapKF0LAOGtNIIZOx3Hw37/1LXznO9+BZVl1zd2GDRvwta9/XRFzKzDXXOAlxFUkWgZj305oYydDCeQKwzISRO5caBJGK3UJa31SYwEOmjPlHdGPHaygpwrw3j6Yq9e2LNK8/PLL+O4//7MiC16nZV3TdSVm/+SnPwW1+qQ1DcbZ54OlUpXVElV5trFLTjRlqnQx01RSGUukmh+zj5dfeQXf/d73YNU5d/JklnO3/qmn1Ny1AnlQyHmrciNooyf9mIzgt3eQV/QqQFIgtUJDocZWm8rW+mitBkcNQ4q2xw+qSkuVArW0+YtVQZdWIMXAu+65BwcOHKh5Ok4dGkOxUMBdd9+tjHutwli6EtqceZVFCWri9KnWd4XIK/oTgO1CShf33nuvslk0One2ZeFXd92Fw4cPNz8Arql8E5ZMTf2yfo6Jfmhv4EZPFoZKIhBIa47ACYOVJIwWDsVaH5WEUatnSUOQpHD8sGr7PzVTEdCXrlDxDK1geHhYSRjNxPpyTcP27duxa/fulsagrtU3AG3R8uriW4P9VE7v5Fb+BkFb4NUtbRWjo6N46eWXlXG40Q0k52737t3Ytm1bS2PQFy6FNji78vNzXXXgKO9awBs8aJnFFcHU2AjNhuG2JGFQVdKQUikPopWFH+qrDx2rnKilGyryr1WcOHFCuU5ZE0E+UgQfz2SUdNIyuOZ9n2r1MqoRQBVUDfiSUtviFV7tzRYxNj6Ow0eONDV3kmCyuVzLNiBVrHnewqpzow2fUAmLQRIGU1J0sJThlqT+rgzcIsBxRdO7WtSoecHlggwkws4rkqOyDyffy88bCeKUtG27paAiIYQy9gUBfe4CVYG74uSKBoQgqiEGapoq2BsEpGTR6tzJ+W8FzIypjNZq5fykOsvyuWDL6YWwMUsSRqujDMfoqfTP5hPRyW9IWwlywHoQRiZ5CasInh2vNADwZDqQ2Iu+vj4VSNSMS0t+xjRNzBpszUtTAu8fUIVyKzJ5g8F2Fb+OHxXLZ81paZwlxOPxlueuf6D1Z6jNnuu1QJ8MBvB8Vr2CROChAyS1p+p7qhGE5iVREkaTENPYMcyArNJSJWHFYgXaJa8dQDze8j1mz56NM888sykbhjwh58+bhxUrWleNJFgi5UVdVuOLejukqz+uXAxZzhlPB5O+3t/fj9VnndXU3MnNMXvWLJx5RuuuXXlwsIrxJEz1P/Gym1u+zan7Vasf2wLkfgwiZT60XBLbad5TIr+YW+OjkjBaHzjz+otUSjaT95Y6eACVtOQpecdttyGeSDTM8PLvr7nmGixfFlAOi2GCxWJV80oaQ+UPMDOuXkEglUrh1ltvRSqdVuTZ0OiIcOWVV3pk3SKUl6RKNzQmXM9oHiBUEe0Ar0f+fgzClxMaYThu835f8nWuajA4D6Qpi9/Su+I7rNTCMADcfvvtuPqqK6eEM9eC1N2XLFmCz37mM0gkWzcgQkU082AqmtcMlNECTf+//bbbcM1VV00Jo68Fx3WxcMEC/M5v/7Yi7FahGk9Vc+uSAFNt+1u+zQSCWdunIPeh7TRvUyxHaCX6pAgk9aZmv7pTI0Xe4EzZMVr//kFGjVbHokWL8NU/+ypWr14Npw4jnOu6Snf/8h/9Ea699trgBjKd3tGFOVTz58/Hn/3pn+Lss89WJDqdlCbnrjedxr/58pdx3XXXtW2cQSJwwhCehBEEQpMwXOEZPpvdj7UaFmk8IDsG95shV9gp5NiBBuRcf911+Ju//mtcdNFFE9Z/KWaXDLzyJRe7JJQF8+fj61/9Kn7/i19sKGBpOpC8n11FymmEO2s2jqkutTULqZb957/9W1x6ySVqzirNnePP3by5cxXB/MGXvqSMnoFANciuIuEwDtKMwKRR1T8kQL5gikSFkviDGGJoHXeEIBRtgWaTtD2vbOUMNsnApmQNu5XqLwQYBsgwp/IFY6BCHrCDK3zJGMMH7rwTK1euVBmXDz/yiMpYzeXz6tQ3DEMt9nXr1uHzn/scbrjhBpVQFSisQuV07YkxNnKxyuX2ySqqV5CQc3fH7bdj+bJl+D/f/S5+/fDD2Lt3L/KFgiILOXdz5szBussvV3N34403qt8FBbUWSs2wJ7+naSAzFph4xsGClTCYJ120EhdVjtAIQ0oHlt28ZdZVXdorq45yOuMab02ZkCqPYYJUvkOFhZ/NQOSzXgXuAHHOmjX4q29+A1/8whdUFOLBw4cgXIHBwUGsXrVKqS2t1nOoBpHLAPlsxYXfSE6f97eVS/JTMa/mLgysWbMG3/zGN/CFz38eW7dtU0FZruNgcNYsrDrrLDV3vb2tReZWghgfAVWyP0npxoiBAqzCJsmixZU9BXIfBhEWjjAJQ6Jou2qgzbRoU7EcRIhVmbyYzqFx1gJzeg9bqHL3UxvYUC7rNQUKoXeGYZhKJ5evdkKcPAFRqFDgGI2bcxivQLOKMIpwh08grE4tUuqSxCBf7YI7dNyTMKYEDBIokYRIVHZVNwOtxTajkyEP7KJ/cHdtX5ISSqJQs+O0a6jCMc6UHaPp5yRPB92A0z97qtKoFn4B7tHWU8u7Ce6RgypuoCJ4AwuqViii48A98i6aN8f21kG1Eoc9faB4ZSm1GQSWJ+XDMw0E14QmPMJQupPwrLNNzoFTI2FG5wzxVg2CmgZ3zgKQXiFc2nXh7Nvd1q7docKxYVepugVfYmhUwqgIqUoe2BO4HaNTcMdGqhMgg+rsTvFEII1E5LkVSBSzD89bSbBrnbwNIjTCYH4sRdFqnt1cKjVfroyE3rodw5mzUImVlU4IZ/87EKMnW7lD18AdOgb34L7qBs8GuVf9faVLMQb38H6Ik8ebG2iXwT18AK78LhXKN4LrsOcurHzgNIHADZ4ALHlou40f2tW+TV2Ewb1A4IZnREoHRat5w6cKOKlho0jqvLV4DBKqJqMzOHfqA+cM7rHDsPe1nlreDbDfeVvZMCoaPHkThMGrSBmMQQwPwd69o/nBdgvk+nt7MygzPtV+IdWReALuwuWBuVQ1HjBhqP3n2REbvapV5QN1EYbhcilf1nPUyl2Xm0gFIaDgD7gZqJBWUT2k1VBqSQtCEhFEMg17aYV8A8ZBuQzsLZs8g9cMhlQP7M2vKQ9GxcXdBGGoz1RMr/DsP/bWTTNeLRHjI7C3vVWl6JCAOzgb9rxFgfU1DCYL+xTkqApF0YxWPUIaq+jqqpMwjBwx8bi80DR/egxEvwQwqv7FgIItlC2jWd60aqRdS+kiaWitqSWaBuuMcz3X2OQbEWBtfhXOsRaqNnUBnIN7YW17s6qRQm38JiaxImF478Da/hacQ63V1Ow07Le3enasKgYbe9lqiHR/IIFqQdsvAC9DtdC4ScAG8JhOOFHpzboIg5mcOMQDAP4ZQIV8cAVJEt8WjH1LEYe/Bh1HeHaMFiI+p1NLWrIsE8FZuALOvMVTDZycwz16GNamF5u/fqdBAsWNzys1oWLxHAbwJn2gkjAqSiacK/VH3jeUrsJtgJTGCi8/4wVtVSjfKA+Y4llrg8nNUd6RoPKjPDA//kK+Jl1WHvoVyUB+BMADxPE9GGZFd1pd3/bqtUk8+MaRk4LjLwzB3yASt4FjjhoXKfvGEU3Dr/NW/m5dS0hK2w5AOcrlHswVBXqbDPmUXGEJQkyrPJkJjSOmcWQdtzlOEgS3bxDF1RfA2L9r6vuui8ILT8G88HLo8xc3c4eOQp6QVmnjVliQvNqmrwPKjmFULwYs7+tcdjX0Sipfl8Paugn21jcqx2kLAXvhMthLmitbUAl60PYLBuQtV3lJyiBH+6Cu4Veuy24HaCUYvKdPGAPYc4LhJ2u3D+1d+rHKfXDrVppm9Q0grsWHfvXU738bXPuiS/g0EX1KEH2aC/q/bv4vqe+lEulRjXgewGvlhtZ80VXiUbOwpnGvplpSS0idiMVzLobbP6uylHFoH4rPPz7jGvCSVUThmUfhHj9aVbpgZouNbYwqn5fzdvwICs8+BgowxL4dEJkxFJ5+xDN2VmidKaWK4jmXQPQOBOJ2Z2HYLwSQLziT+czSdbxwy9pZv9TA/zUj+jTz9vCnBOFzFud/Y2r63l3nV6+YVvcoL18Ww83npHHHVf8RmqaN6oZxWL4M3TjMNGP8l/8auHHNADbtzbnEaOOEvYN5npIKolHdcASpVzX0GLw1/U+eGAuWobjm4qnvqRrtAoXnnoC1/c3m79EBWG+8rLp3VYOULJpVR+q6BhEKLz0N661gGjK1BUQoblgPa8umygZiqcLOXYjCuZcG6h0JOv7CdgXyxSlkNuw6eP3B14R8aDndMI+qfayrvXwyGU+4N5/bhxtWVW8P0bAC9pFLaoczX3jmIBwnK1WSPQAGmF/tR4pHyXhzsq/rqyVmFbUkrnOlmoyJJtUSCc1A/uKrENu6EdrJE6efyIxDDJ9E7td3KbWEDwZTgi5MuEcPIvfI3d4pWSXAjbcoXSgw7zrCruC8Zxw0Nobcw3epRtZB1EgNG/aurcivf9BLPKxU14Nz5C+4Au7sBYEF9emB1Xc5hYLlVjqkd2q6/vbt5zYf8Bh44NYt5yblxj4EwqbSElJ2jLzTUiOVYg21RGMMabNFbwkJ2IvPQOGiq32ymByXwZVOm33wF6BCrpU7hQ4pUmfv+ymc3W9XJQtm+IQRAJhe41oah7NzG3IP/Ey5qbsZ7omjyN7zY2XorkgWwoW9aAUKF14VaDq7EbQ6QkA+707Os5K/ftkGDbVy7VAiPdOHZ2XB2IuS6NQvGJArui0V8bCnUUvShqZS3lvJLYGmI3fZ9bAXr/Dy68shn6wUV59/wjuBWqhmHSbIKiL/yN0ovvJc9T9igBYLtOMkeKya99G7SeHFp5F77F6vzkgXQpJs7v6f+obOCl+ECBSLI7/uJr9jezDShcaCVUfgR1hnC+5k+0WGAS+OpvtbegDhVNxKqeTxlwAcRZmLJ190myZmyRWFGobTmMYVabQEIZSomb32/aBUeqoF3M/GzD30K+SeerDrFj9ZBaWG5B9/wGsSXGWyJVmwgNNJlS0jVu1NBlgW8o/ei/zj93WdEVRKPrn7foLChidr/BGhcO5lSh0JEsGVm/TAmBfdmbem7LXdBGxKtpgkFwphvO9KBo3FdvpqiYIk5EzOaYmYpVpSLbdEzk2fqbXO1lKKWHMpcpdeNyFVnAbuRYDm7v0p8k880DXRjFJNyv36V8j/+i6/SE7lR6tiJ6pt7BYhCaOqaiLnLZ9D7v6fIy8ljS6ZNzE+guw9P0T+qYerFsmRqoizYAly197pZaYG5EqVS9VsJVK5EgjI5it5JelVXdMOfHhZa/cLLfmMZ90MGJ72I8cUcgXHi/pswVtSrCFlJHSOtK61xqG+6Jm77gMqNqPi4mBcGRNz9/4Y2Xt+BDE23ModW4YYOobML76nJB+5KWslmGmJUJqN+zcAeLxGXIcKt88id//PkL3rBx1P7HOPHEDmR/+E/PpfeypmRbIQEOk+ZG76qLJfVC3V1wR0zlXAVpCQeySbn+JOzRKxZ5b05ls2IoVWQIcl4gKU2wAmDgJYrqRSmxRpxJqstahi411CokpBb6kPSilj3HZb61QtVZO+2cjc+jFo4yPQD+yeagSTJ2ahoMRs9/gRpN7/MejLz2r+ns2ACPbOrcg98FNYmzd55FbNgMb9zRxqyaRTpOTkqjSXkfNWLCL/+P1q3pJ3fhzGilXhDmoyhIvi5teQe/DncN72e69WcaGSYSB39e0orn1f4EWSpXQRaKwWAwpFV6n+p9unaL8Ae/Gk1WzBzFMIrsLsJHzvH/4Sn/vDr+YEicsAqFbewu+50JPUm+4dKfy+JNVUD4Mz5Byh1JfWvCYE0T8Lzqx5MA7sBs+MTj2afZXFPbQf9va3QCRUlywWC6YtQC2I4RPIrX9AndTOnp1+FFaVb8y8TVzVxhAwmE/oVM0uXJq3wwe8eROu6izfjnlzjx1WRuHcPT9Wz00RbBWygKYhd9WtyF7/4UDrdsKXLhK6FngP1eFxC+M557S1T8B9RZg/vPWcvpYt9aERhsS/+PzXiw535oDhRjlHzDdeppM6jCZ1N/LrHsarxGSUDEiZFupwnLoZqfR3t38WzIPvgGfHKpMGY6DMGOwdb8HZu0v1NNH6BlTbwKAhxkZQfPlZpXcXNzzlp17X6KEiySLuk0X4HRVO3VavgzT8eXO2b4a9d5dywfL+WeHM2/AJFF5Yj+zdP0Rx4wYvR6Ra/xRfUstdfgOyt3zMq/sacE5MXNcCt184rsDx4aKS5MuWQ4aB/Xe3SK/95H//fy3fI1QBVTMNQaLwNIB9AJTcadlCGT8TZvNcVXAFkoIpaaISegxNhYtL1aTlPUKkwoBHDRO99/8A+qE9VQN6YNuw33oNzq7t0FechdglV8BYvRbanAVgRvNBD6pc4LHDsLa+AevVDXD27lRivdfKvsai4z5ZBBGg1QRKEo1bqNH7UqooTmnetkFfuRqxi7150+fMV93amoUkBffIARW1WZTzdmCP8taoPhXV5o2EKoiTX3cjMjf9JkSqL1C7BXzV2Qw49kISRC7vqujOSWfHVsbEC0YsHgjjhb6MHn0rkxSi8C0ifA4+efekdCydn1Qhsc0ibXD0GtUnfbjo4FC2GFxrEc5h7tmG9K9/CnPXVu931U51+SVJALqpRG19+Zkwzjgb+tIV0GbN9Xqc6vpUyUB+TriqQjVlM3BPHFFl9ZydW5Xk4p445hnnqonRZVBuznhwwVmtQFiAyNeRBa6+v1AkoeZthZy3NdCXLIc2a55qJM10Y+r3l5tcdeuxIbLjat6cvbth79qm1DUpXXgekGnmTc59IoXsVbcje90HfI9I8CUapSqSNII9q4kIh47lMTRul29qF6C/c3Xja3ee2x+IWyp0wti2+wT2jNPHAfZPAPrhx84vmZdAb9poWtLTGcNgrHoOiUuE/ZkixqwApIwSOIc2dBSpJ+5C4vUNYMVC7RO+RBykyl2rjvCsvx/awGzwvkHVtJjFExP5KlTMQ2TG4Y6c9Cp8jw57Xg9lwcf0C94HMzzJImwDZyOQqombr6GinPbH5fNmgKdS4H0D4INl8xaLn5o3KUlkxiBGhvx5G/HmreQmne409+/nzFmA7I2/gcKFV/pl94InC6ky95hG4Lkj+YKLvYdzqkJ42RI5CuCzMXH00RsuOjeYewVylRp4ekcBmczoMq5p3wdwDXw7xKxeEwvnJFqyEvcYXL2qQZLFgUyxZl3QhsE5WD6LxGvPIvnsQ9CPHT61maeDWph0Sh9mZVIK+f9XGmqp538jE+RHXFaPuuws5P4TBU/iaMh+WGnelJG3/H3/vxudN6lu6AaKq85Txk1rxdmnrhkC4rpUl4Nn8uPDRRwZKpz2OwIeZOCfddMDJ+88I5itHvoZdO2qOB5+deQgwfk1gMsBKCF5POeoiLREXGv62eRdQlyjqraMtKGh19SUehIY5IkWTyF3xa2wl56F5IZHEHtrI3hufPpFWmsht/I8mZ/PEWs9+zRMSBJTcSA6IIp1ShuYZt7Q5Nz5a86ZuxD5992A/KXXq3iLMKvEa4whFmDryxIcR2AsY08ueZJnhPvStjZ8dUBkgbD7kpSgxXWHET0MYD/852vLL5m1WyJyRxDyNfJTJI8Mxg1FKIGeF+TVDbQXr8TYh38Pmds/BqSCdbvVC7n55CbUUt1NFhPws1vleBV5hOqnqwGNoXDRFRj59B8he+0HfONmuC0lTK3FMgwVIK+WyTtTQsEJ2EagpygdjLGzhLYQxs3npJFnsc0EPDohfBMwlnVaqpMBX8qwpinhJ0kjFN1LCIhYAs6KVeADCegpUpshdHWA+XaKpE8UscCSJ9sG5geSTRBHk3VFG76vynkhaP0GCu+7BvayVd6NQ7BXlENJF3oI0oVLGBm3J3OdlN0eEpq265o1wbqo26bpfvj8noJLdO9EvU/m5eyP5+yWDmaXCDmnemVxiYGYrtysYZz/jAjEuYoI5GWbWG0CI0DyKKkdcUBPea9utVU0gpI3R81ZEuEQLj+dYOWzQUxXwVisTRXhJVkE3dVMXi5bcJArTE40o4Mc9P+z9yVQclTnud+ttbfZRyONdoSYRUIImc2WhYUWsEViHib4OAbs45N4g2MH85I8h9gJNjbmxA7BwHNYEoixXjACO/HDBssGIctgErMaSSCBJCQQQpq1Z6ant+qq+nPurapRa6ZnNEtVd8+ov3OaQV3dXcu997v//v9cVzXfs/yKZkd/4JXX0SzNeZ5Av2XAlfx+uWDA2bEmqkJRJj9LMpaNkDV6MBdXSRpDKrKWPWaK/ORAjkVdUd2oMjdoiS9uz9hvun8tNx6BhtnUhjWpH2qMzNyoybxXKeIpigHhANIcCxd/Tvkv/szIHqfG55k7pDGeHSd5WXXGrQhQJafurN+wbEe6ME+MaiYi9mtbrX71w23+31/RCOPP37cct790sLddrvopGC4GUMvcep+JlIn6am3SEgDngKRpQ5PkgjVbOao0GbWmgu60/ynpxyff8HT4vMmKPKKwh/37+MePN0VmE29fOFMw4pnZJ/6FfdyphHyClfLIgo0hP/PfUlTxCvxemOMZ8builgjUSlnCfjHslztsSf3PS7u1tK8ndFFUT32jHiPLYk/LoP8CsAlu2ns8kRP5JVORMgyLkLZsREf5Df5QG3QV6ZyNwclWGC8Ecnqb2OOJSGQjJ/IpyAcTAztOHj7W+xESISf6oME3scmmQYwFLl3EE4awYZwY+seelmD990+bKZDZVVQN+FNnzuKyejeBHvH6mzhBJyYGUlNzffLHkzTH7mGiyQyzwuqobthJn5tLGGqoFE6SCiYFR410JIzgBk1mTEgXfi9bLwx8cOSa6QHhkRfS/xa/siWYrajoJjNNVYmBPQngOe89i4D4gCH8yVO5Ta7LDZr2mOHgMU1Gg69eEwJJMkgtUipoBb7A5iqkrAbGF8wN0vLbjQq3o1nvgCGaLJ9o68R2yWK/ba3a6Ps5PRSdMC5uj6BKo6ME/HhIyoBT87M/mZvy+GVMGrOUHz9Xva6gWvNRGxNeEr2iX0wXEECqJog+KKiiwZb/v+/FXQxPYQfQZYMeshQ5/ollK30/r4eSOOWYotlkS79kwFDTDLKB3oEcjClmmDqqiT2masJZf1ZEFZZrf1L4ZNiqXtFIphFIC4FkJRCVhKsiYUUJJDbGdKWLYSX4bID9GjLboanB2mVKQhirz6iBoutdNrDZ6wrvVQuKD0xdyuBkMZgbvS0B3BaLUy4aDHe3kpiYgBURY5qAwZEIfU4xR8CqCP/FgWQOydSIAr8dJNPmTX/fEN+4LOL7efNRsrAfRVHIluwnAfzKczQSHI/JyECUiSNj2UgNbxUw/Bok5sMSJ6fRkRaafuGWpyiEZ1YNJupNV+RAIjpFNfCcjZ5+Y3gypc3A/r+VTj7zr1uCry1bMsJY36Lj0lWzemyZHgRwDF47AtN2RK4pBlgJ1SQ3etFgcnu2+lT/2fGSCMKoKCblDybGi7iE4eNwKZIUiFcEbipFPGE4rTpOPHSACJujsfrU57T6AM58IkoaWPzi8zaytvlbEH7qFPtwxa7BHBLJEUadCYMzcSJnwyyQ4ZbK2Rg0pn4OAS7iaq6IW+GL8ofEYIt6GgU63E0SMmOIBBD+Dc8pkDbRN1JdN8DYQ7KivLSuvcr38xZCSQnjvPfJqNGr0mBCytjjvW/ahJ7+rJA2pgouRfQbtvCccGGDk0jatEXKu19h4kLE1ULTP7HjlAANSRi+tTt0q2gFEaAFN0iLqyLGyLCDVxiZD8mKVrQmLyWf4etbY0jJyk4C+zdOpHAHIJm2hGriB7haEjcs9GT4y0afYYMxyVdd0xFxS5WrXcG4QQAxyVcjtSjoG4DdwkP/YA79yRFBWn0g3KdC27e+Lfhq6x5KThgc1aqSY8zeAhKNjwSEAXTAEE1Z/NgIuFbCVRP+IteIFPaxcjOpuqMTV1D2YJLkmxtcl4OzW3htD7v7jeF9dvgk3moy/FwOKUVVgstihm9srcLL/z54hGT8AMARDBlASZQey00xAnQ0SFzvVBVhrJoqbE0XzZwrRozyh4jM1aa+K6uSM3/8TizzYFmE7r6sCDcYdoa3iPCDJWc1dK1tLY7twkNZEAbHBZ9pgpKj7cREBKhIKeUPKZE2haQR1DIUxip16sYqUriEUQZVdwOqRTmT4NQvmVrqtyzIQg2MLLyYi77BEapIhoh+OCjj+WMHit/UumwIY0N7FMbsZNKycB/Afu+9z+d/T78hEm2CinJQJUkUZp3s4DMuIXIRVy4tYRBjhdPsK8gDifYOthqa9C/wzSUqJNPgyCKdtdAVHxHRyf/xNDE82KA3GOuXFj9/qWwIg2POW4uQaIjsJ6K7hipzuapJZzxbyErsG1RZEpLGpEjDbSPgFNEp0WJ1i8Jg1YcgzV7ge/MdX+D1fi2xrYcT+2STBT01Vg3wHiyb0MVVEWNEAONhEO5sjpnvrn+jLrDzj4WyIoxzLmSoZhoZdu4JG/SjfNUkmTaFPjelJssngS7LLmlM9JsEW9acDMgSgmwb0qJ2hC/7LOQ5iwIvajsh2DZYrBryuetBsdrAa2iOCU6sqoaJloaWhGThf4vD4egdMNA/UhVJA/QvhiJvz7II4bK+QK9hNJQVYXD80QIFkUjVIBjuAfC7/GPxgRz6T+zs5DsEaSjKxElD7FqlIwzGGGwzh8G+OOQzzkb4ii9AXniGK2mUWEWxLbCaeoQ/cg1wzkbkiJXukrgkpihuo6Lxf01ybV1aABmoHkQmasos5BXh+JUF9mCVGjLev6QmsGs4GcqOMDgubovByDUeIOB7AA5575s2oSOeFYVPAyUNt5XduNUTkYA2eTHXL9iWhe6Oo8jlTChLViDy8S9BXX6+E1BWClXJbX0oz1+KyJ9cB+2CDyOZSsPIpEuadsMlQVsef/EcjyyCSFf3wB9HNmejozfjVNI/8fAek+F7lx5qOLyutXgxF4VQloTBUVWVhUzSNiLikkYS3kM1bHT2BmvPwAnqyXjOQqLBr62GSpqvKoHQ+c4hpJLicUFuPg3hK66FvvpSMD1cXLuG6CimQF35QYe4lp0v3u7p7EAunS5pop6QBMdpoC4GWcC1W3TGs07i5YmH4jZwZ5ZZzz/TWrSAzlFRtoSxoSUEPRTO5oD7AfzHUK4Jc7qm8Yc71QS1k4FPkqiqjMvl6kQPllbCUGQZx94+iK7OjqH3pJpGhC79NMIf+xzkuacNNWEKDK5UITXORXjTp4RkIc87XRzK2TYOH3wLOSMjVKhSwYnKVU4qYHjekKDJgj+y7v4s+hIj3KQ5Am2WGB6OhKLmh9om79nxC2VLGBxr28KI6OFugN0G4Pn8Y/EBQxiHgha0NVkaH2kIwiiduEguYaR6OrFr56snXpqqQztnAyKfvAHa+y8Bi8ScRsV+EgcnIssCC0WgnXsRolfdAP3Cy8AixwOLEolB7N/zGmRh8CwNYTDk18IYu8hSVFMCN3DCjbfo6TMKDcdvJJvdqYYifZvOiAV+HeNBWRMGx8b2GCLM2knALfn2DC5cdMWzGEj43zZgOFRZQkxTx3alMSYkjFKaF0VncJjY8fQ2ZLIjg3qEivK/Po/In14P9az3i8UtVIepeCxs2zFqhmNQV64WpBS+4jrIC9tGJOO9/fYhHNyzG6EAmhFPBLY2dt6PJkmIqScZbx/gef86ejLIjWz5+RqzpVu+c/bLBza0BFsUZyIog9DEk4P0KCnZ5JMmSd9nwDe8niamRcJIpCgMsbAS6GL1dpx0zhQNkUaAsZIX0SEQ5sRCePm/n8Ou3btx3jnvG/EZpmhQ28+Hsqgd5oFdMHb+DuZbr4ESfYBl5jU+LtAAeXgXdVWFVDcLyukroK54P5TFywRxjIYdO3Yg3dOJUHstqIQRqU791cLjpIt4nODCvT3wX88YFjp6ssiMbBfaScB3SbJ/d8vrF2JNoFcyMUwLwljbGsWONwcNK515EIQFYPgSH1t+jD/sYz0ZzJ8VRkgPph2iB0+nlZiFjGnhxOZlDLYeKSlhcKmruSqMROfreHjLFqxaeRYUpfAQc1VBXbEaats5sI69jdyB3bAO7YXVdQQ02AfKpl3pw/2CxABFE1KJVNMAefYCyIvboJy2HHJDsxO0NgaOHTuGx372M6zRJLFzBxlPMxZI1PMMu56j48TvpaiLRLIijKFh8nmbxeBIj1+SiP1gkOUebQxVm2tK7BUZjmlBGBxrW2LY/maqbzCTuF0leSGAP3GnsbAsH+3JYN6sMDTVp8K+o4BPprBr00iZ1gkTn7yyb6VaDESoD2mYG9PxyKOP4sqPXY4PfOADY39J1SEvaBEvyqZg9/eC+rpgD/SCkgOAlXPuSQ9DilWDVTcIQyqrqhXSynjx2M9/jl1/eAVXrVkKmWHMequBgjnFc4gLUO41iKK9RfCEeBAekd6ssF0MI4scQA8Rwz21oVh6XWv5qCIepg1hcKxriWDnS5kjR+TkzYxRA3/Ls54lUqaQNJobw0JFCRLMjdWQJCZUFK9CubC+MwmMzJIY9cjdJZfNqsHW3+3F7XfcgdbWVtTXj690G9MjkJsiQNN8X69rz949+Od77wUzDSyujZY4jIy5xmlnfLi0E1FlXzKWxwNbkEVGGO2HHyLglxZwa5KqOj/RWp59bsre6Dkc++vSqIprrwHsGwB25h/rG8wJm4ZlU1GWK59sMU1FSHbEWFFYVpJLGljJd+/ljVXQdRWPP/EE7rvvPuRywRuGR0MikcDt3/8+Xv3Dq5hbHcG8WKh00gWcHjK2FnIkRUVGTPOnvMF4wCXA7r4sevsLePcI/wXg5lmmfnBBrPTxFqNh2hHGFUvqwOo1MiPaszbR3wPYl3+cM3dnTyaALu2FIQJ7NAUxVYHERd0iibWjgd91W30Mc6rCSKXS+Kc77sC/P/QQLKv4yWiZTAZ33nUXfvzww+LfS+tiaAxrJTR4kpAAZT0kxqsYxs2hMwuyMNDVZxQgTNppgb7WFDNeOlCfweql1UW5pslg2hEGxwdX6ogylWSb/ZKIbvaK7sBdMD2cNHozQvwrBphrXQ9HIq7xr3RbKL/l+VUhtDXExG7a3d2Nm775TWzZsqWopJHNZnH3PffgtttvF8QlyTJWNlUhpARrYxoT/MSSDD0cDaQVwKindUs0dMWzhebkARBuSqeSzwzaNbjqtKaiXddkMC0Jg2Pd0hD0cCRnZ9gjRPRtAEPhjd4AeepJsSCpOpgSXL/O8YDvZDW6igua64QrmC/Uw4cP46+++lWxgJNu2HiQ4CR1y3e+g299+9vo6+sTRtO6kIpVTTWlb/WkyGCinmdxBomPR09/Fh29BSOT3ybQ15MmfhGLVdtrz4gW5ZqmgmlLGBwXtUcQqQkZKsk/ssn+B9G92oVHGp1FtGmILu6lTnF37RgfmFuPhrAuJqwsy8Kt+Xc33YS/ufFG7Nu/P5hzE+Hll1/GX3zlevzjbbehf2BAnNsmwhn1MfEqbUEwEqntIpekCNdxfA4WlCze4xudRew/6mNR8yNnBd9TxA9Ma8LgWNce45JGyrJy94Lou4VIQ0TSjdGg2R+Qo46UQcUriwjLZ1VhZVP1kL7MF+7AwADuvvdeXH3NNfjX++8XJOIHOFHs378f//Dd7+KTV1+Nh7c8AiOXgyRJLoExfHB+PZoiWsniL5wLdWthKMF7IPh9dsczo0kWRwn4Zlqy/l8oFDHWtZWf+3Q0TCu36mi4sC2Ep/b0p8xs5m7R6JSx/wNAUDafn70DhohgntMQgqpMtGzK+MFkRRRmKTX4PdfqCi5e0oTt73SLycuEg8DZH1548UXs2bMHWx55BFd87HJsWL8BixYtgq6PfyFxkkgkEti7dy+2bt2Kx37xC+zevVsQhZxn+OWfa4zouGhhoyiaWyxj9KjXrWqgkwSZTQXMq5gVzzp1LUbe7zGb0a2KxTZXRWKZjWUYazEWZgRhQOSc1GD7nv5ENpv+vyCZwNhfA2hEXps5vnA4aehBBHd5u5eql00h3vULG9BaH8NrXQOiaK0HRVGQSqfx1LZteObZZ7F40SKcd955uOD889HW1obmOXNQXVODcCgEVVWFsTSbzSKVSqG3txfvHD6MXbt24fkXXsCrO3eio6NDfIYThTzMS8Sf+bnNtVjVVD28J2gJQI4EGKBhOifKSWacxMiRpzgC4FvMZD/SI+H02tbyt1kMx4whDI6d+/fjzCWnJ7NG7p8ZkGMMfwNgyOzcP5gT7N/cEEI4gDBykuWSp7h74Dvb4poILj19Nvb2JNx+X8fBpQ3+Mk0Tb+7bhzfeeENIHDU1NWior0ddXR2i0aiQOvhnOMEkBgbQG4+jLx5HMpWCbdtDv1MoBJ0vmIiq4LKlc1CjKyWXLsRDUDUwWfV97EXt2ZyNY70ZURWuwO8fBti3sqa1OVoVzaxtmX5kgZlGGNd/9Bzx9+m9ycHBdPZuldlpBnwNwFDoYiJlwrLSQtKIRfy8facaNXzsqDXFqxEqwBUtzXhs/zHs7U4UrHLNGHOkAlkWBMAliO7u7sJSEmPi8/zlEcVY4BLF+XPrsH5hY5kIXeSojLL/wXWprOnkhqRG1OLk2E+Em3Ky/JNwWDc2TlOywEwwehbC+rYoYmE9Y1nshwT6WwIOeMe8Eu5HOtNOc1s/J44kl7xMXz64NNVWH8XH2+ZBkU+uhnlEwKUFRVVHvhRFkMvJiAKuKlKtK7hq2XzMjuploI44IC3kezsIvgm925kWfwtgNxF9VYL5aLUeMi5ZVh51LSaLGUkYcEkjFI5ksoweItD/BvBK/vFszsZ73Wl0xTOi98OUZQK3ZydKnOI+HBJj+ETbXFwwt66oMSn8VBef1oRNS5pK7jUaAh8XPj6iFsbUrom5Bt3efkNsPunsiJKRNoDnQOwv+tOJn4XC0dxFLaWvmDVVzFjCgDCEhlEdiloZK/W4CXwFwA53IMXc8eooHu3OCAKZYu8zEVnppE77dQdTB9/ZF1SFcO2qxZhVpJ2eP9cldVF84ezFwltTatPFCRiqtjV58LmTs2zhMj3akylUX5aLGr8khq+8p9T/prG20S52S8OgMKMJg2N9SxThcLX1R8sHfkvAlwh4lAsY3nHPg3K4IzWaSDl+8Jmkh9xKU+WzSvhO+JHTmvCZFQtFwlyQV8ZVkSpdwZfPWYLz5tQUVaoZD4RKwqZmw0ilHZW2q88JyBpezwIMPwLh+tnp9AvNGmhje/nmhkwUM54wODa112HrgTmYk1V3G8T+CsDdAPrzP5NMW0IP7Sk8CcYJJiakUxPDr6ufOkiUnWP4/MqF+OgZcwSBBHF5nHxlJuHTKxYKNYiVsP1IQTB3fITxd2JXxtz7608YeLczhf6kWegnugH8k2GzrymKcqCnoRGbWspI3PQBM8pLMhY2tUZwV2cvVnSZ76Zz9A0myQdB7AYAi+EKB1y0PNqTFUbRWXU6QtoEXa8M7oSUyq5VIVdFZkd0/N3qFiQME08e7BT2Db+ms01Og+I/bZ+HG85dgpgql42h0wENFQJy9snx1zFlboUsvpn0DuSEe7jAc9sLYt8zrNzD1ZHq1EXt0ysga7w4JSQMD19uqse+dBNULdSvEt0DYl8B8Pshu4YrvscTORzuSIv6GnzOj39ReUa18nysfAGfXhvBty5sEwZJclUIP35XlRiuXjYfX1/dIlLYy4ssXIFCVHYPjXtAvY8Npky825EWqekF8pIsgG2XbPaltK5sDumh1BE75fvllwvKc2YHiM+dy7BxWS30cMTY06k+RoTPAXiIz4v8z6Uyjp56tCc9IYMoO0lF6lKD747t9THctm45rlm+QNSwnOziJvf3miI6/vKCpfjGmlY0R/XS5ouMBckljHGMJhNRm7ZIXjzcmUYiXdC+xdXafyGwaw+dZWyLauHcJWfW4urljUFcfVnglFFJhmNNSwxP7UkT2bTLytl/DWa/DtjXAmwB8rwoPX0G0hkLjbU6qqOKKMs36nogcuIwZM9tV576KyeIRdVh3LymVVTnuv/Vt7EvPujYIKSTqymcEPhLV2SsnlePL65ajEsWzxI9PMpOssiHdHK3N3PVq0G3+bcgikJSJsN+EO6CLW1WdSXevjeMC5eXPo8oaJyyhAHX7crx9K7+Y6k0u00OYScj/CVAawAMZSglMxYynWnUxlQ01GiiOvmoULlKUv6PlS/supCKL5y9EGvm12PLnvfw60OdONiXQtZ07C/568rjAYkBtSENZ86qwmVnNOOjp89Gc0wfIpGyBpf8+PiMcp1ef9PeAUNUbssVjs/JANgGYv8oE3tWCYXNde3lVdk7SJT/zC4CspEqhKRB49iRmscbmrreZJCuA8PVAGbB23VsEhMpmTEFadTGNFFs+MS550oYAWZD+glvga9orELrB1tw1fL5eP5oHC8d7cP+eBLxjIGMZYuQ8piqiHqcyxqrRDLZyqZqYUSFG3dR/iBHVdRGBk8JadIipwNZvyHUURSWD98j4AFidP/83tSh3rmNuKjl1CELlK3MXCL8+rWsKDWfysZjErFNNsP1DDg/X9ogd5eNhhQ01mqigZJQU+AY1aS+Y9A3fxus87AbUTg9wCeC7N6HYdkYNCwkc5Zo2sQJI6LIiKqyKMevuG0Cylr9GA6yQdX1MK66Eda8Fqdbm6t+pDKmIAonz4gKaSxZAM8wRncyQ3vSCOUy7y5pwBcjp97yqUgYebhkuY5HX9iJusjiwVd27f3Jme2n7SawzzLgkwCakeeP55MrbVjCrtFQrSGsK068luzUW5huU8kzYHIojKE2pAiVhQ0dJ7fpGSE3jXjiBLjlB7wojIxhCTdp/2BuKFqzAFm8Q8BmInqgoaHxrYF4ArVSCH98CpIFKoQxEh8/7yzx9xev9FAItKeXWV8Py+oOybKvBeFDAISD3RNje/tzGExZqIkpqKvWEVbKo4jOVEDuf4IJ7yoRyKmIRqqGrGGifyAr3OfZnD2aeToBYBsBP5AZns3AyBhZAxevmDlRm5PBKedWHS/+eFUD+vUQoqFIetPyHz5myezzRLiZgD35UT8ir8C0RQn5d46l0NFnIidNb8KYqbCYgu6ELcbpWG9WkAVGkoVFwB9AuJEB183pyT7FFDUzT5+LC08vn0zkUqEiYYyBy9ucVOQdb6QQSSQODyjybRroSTD250S4nAFz8z/PRdyujIUaU4VuuzPx1JRcyw6MgIytoGOAkNOs0YblEICfMOBBi+zXNcj24+vm4utllH1calQIYxxY2xrBjURY99qAyRheNixjnwTpcYD+DMAGALXw7BtMgiXrQgYhrwF6RY4rHcjtuWxBjAtJciGy6Aaw1WL0QzD2nCapab4wdM2okMUwVAhjnLiVMdzq/v+2N5OJeL/xRFi1f8+YfYkE9mkAqwFUC8LwXHfkuvzdNIaKtFFEUB5ZuLAU3Y3CHbLNxAn4jQ1sBqOnGyy1PxlTsWEa9AcpFSp73ySwoSWKpjodqqb0bNra+GML9FkQbgDYdgJL2uqwfAU+cS3nNZPsiOUKThLeKx+CMARzi5DuJ4jhy8xmX5zb9M5/arLW310lV8jiJKhIGJPEh5Y62Yj3HXkPp/WGjuy05QeWU+5XpKgflrOD1xGTzhnxJZc4OJlUJI4AYB+X6EbBAEnybxhhC9n2UwsPNnYebR3A0c5VuHRlZTDGg8pT8gEPPLUP85pnw4aEubduUuc1Nd0hkXntSb8ouTaOyihMDZ7qcRLpzdCqXzzSdsk1zzVf+cayBQYkTcG6ikQxIVSmqo/o/LOPgGy5RY7KWySNnT2uL7E80qiMxsQwTqIY+niWOqxk5jNq63lb6/72lqCvbkaiYsPwEUcHeyTI8kYi1jLuxU+j69wVjALvmU3QJkRgs0gNfczc/+r0Lt1dQlQIwye896kNmB2b3QyGy0GYeLklcnVwa0LFoE4t5BPFRJ+RQ+ASA7vEIuns+OcvC+QSZzoqhOET1m7eBkWS1zKw84dijSejYuQtiomI2zMa+V6myZCpZ2R2sJBJ7Mp4OlkJ25wE/icAAP//iFU60gIwwN4AAAAASUVORK5CYII= - href: 'https://hub-gitops-server-mypattern-hub.apps.region.example.com' - location: ApplicationMenu - text: 'Hub ArgoCD' ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: open-cluster-management-operator-group - namespace: open-cluster-management -spec: - targetNamespaces: - - open-cluster-management ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: openshift-serverless-operator-group - namespace: openshift-serverless -spec: - targetNamespaces: - - openshift-serverless ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: opendatahub-operator-group - namespace: opendatahub -spec: - targetNamespaces: - - opendatahub ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: openshift-storage-operator-group - namespace: openshift-storage -spec: - targetNamespaces: - - openshift-storage ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: xraylab-1-operator-group - namespace: xraylab-1 -spec: - targetNamespaces: - - xraylab-1 ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: knative-serving-operator-group - namespace: knative-serving -spec: - targetNamespaces: - - knative-serving ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: staging-operator-group - namespace: staging -spec: - targetNamespaces: - - staging ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: vault-operator-group - namespace: vault -spec: - targetNamespaces: - - vault ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: golang-external-secrets-operator-group - namespace: golang-external-secrets -spec: - targetNamespaces: - - golang-external-secrets ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-streams - namespace: xraylab-1 -spec: - name: amq-streams - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: grafana-operator - namespace: xraylab-1 -spec: - name: grafana-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: v4 - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: odf-operator - namespace: openshift-storage -spec: - name: odf-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable-4.11 - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: opendatahub-operator - namespace: openshift-operators -spec: - name: opendatahub-operator - source: community-operators - sourceNamespace: openshift-marketplace - installPlanApproval: Automatic - startingCSV: ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: serverless-operator - namespace: openshift-operators -spec: - name: serverless-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic - startingCSV: diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml deleted file mode 100644 index 7a9f94b2..00000000 --- a/tests/clustergroup-naked.expected.yaml +++ /dev/null @@ -1,588 +0,0 @@ ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: common-example - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: common-example - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: common-example -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-example - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: {} - argoCD: - configManagementPlugins: [] - initContainers: [] - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - resourceHealthChecks: - - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - kind: PersistentVolumeClaim - resourceTrackingMethod: label - imperative: - activeDeadlineSeconds: 3600 - adminClusterRoleName: imperative-admin-cluster-role - adminServiceAccountCreate: true - adminServiceAccountName: imperative-admin-sa - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: [] - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: true - managedClusterGroups: {} - name: example - namespaces: [] - nodes: [] - projects: [] - sharedValueFiles: [] - subscriptions: {} - targetCluster: in-cluster - enabled: all - global: - extraValueFiles: [] - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Automatic - useCSV: true - pattern: common - secretStore: - backend: vault - targetRevision: main - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: trusted-ca-bundle - namespace: imperative - annotations: - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml -kind: ConfigMap -apiVersion: v1 -metadata: - name: trusted-ca-bundle - namespace: common-example - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-admin-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-admin-clusterrolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-admin-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-example-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: example-gitops-argocd-application-controller - namespace: common-example - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: example-gitops-argocd-server - namespace: common-example - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: example-gitops-argocd-dex-server - namespace: common-example ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/unsealjob.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: imperative -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: fetch-ca - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; - ls -l /tmp/ca-bundles/ - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - - name: ca-bundles - mountPath: /etc/pki/tls/certs - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL=""; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - - name: unseal-playbook - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - name: ca-bundles - emptyDir: {} - restartPolicy: Never ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: example-gitops - namespace: common-example - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - resourceTrackingMethod: label - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: example-gitops-link - namespace: common-example -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://example-gitops-server-common-example.' - location: ApplicationMenu - text: 'Example ArgoCD' diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml deleted file mode 100644 index a852051f..00000000 --- a/tests/clustergroup-normal.expected.yaml +++ /dev/null @@ -1,1494 +0,0 @@ ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: open-cluster-management - labels: - argocd.argoproj.io/managed-by: mypattern-example - kubernetes.io/os: "linux" - openshift.io/node-selector: "" - annotations: - openshift.io/cluster-monitoring: "true" - owner: "namespace owner" -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: application-ci - labels: - argocd.argoproj.io/managed-by: mypattern-example -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: exclude-targetns - labels: - argocd.argoproj.io/managed-by: mypattern-example -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-example - name: include-ci -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-example - name: exclude-og -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: totally-exclude-og - labels: - argocd.argoproj.io/managed-by: mypattern-example -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: include-default-og - labels: - argocd.argoproj.io/managed-by: mypattern-example -spec: ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: mypattern-example - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: mypattern-example - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: mypattern-example -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-example - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: - acm: - ignoreDifferences: - - group: internal.open-cluster-management.io - jsonPointers: - - /spec/loggingCA - kind: ManagedClusterInfo - name: acm - namespace: open-cluster-management - path: common/acm - project: datacenter - pipe: - extraValueFiles: - - /values/4.12/aws.yaml - name: pipelines - namespace: application-ci - path: charts/datacenter/pipelines - project: datacenter - argoCD: - configManagementPlugins: [] - initContainers: [] - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - resourceHealthChecks: - - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - kind: PersistentVolumeClaim - resourceTrackingMethod: label - imperative: - activeDeadlineSeconds: 3600 - adminClusterRoleName: imperative-admin-cluster-role - adminServiceAccountCreate: true - adminServiceAccountName: imperative-admin-sa - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: - - name: test - playbook: ansible/test.yml - timeout: 234 - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: true - managedClusterGroups: - - acmlabels: - - name: clusterGroup - value: acm-region - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" - name: acm-edge - targetRevision: main - - acmlabels: - - name: clusterGroup - value: region - clusterDeployments: - myFirstCluster: - baseDomain: blueprints.rhecoeng.com - name: aws-cd-one-w-pool - openshiftVersion: 4.10.18 - platform: - aws: - region: ap-southeast-1 - clusterPools: - exampleAWSPool: - baseDomain: blueprints.rhecoeng.com - controlPlane: - count: 1 - platform: - aws: - type: m5.xlarge - name: aws-ap - openshiftVersion: 4.10.18 - platform: - aws: - region: ap-southeast-2 - size: 3 - workers: - count: 0 - exampleAzurePool: - baseDomain: blueprints.rhecoeng.com - clusters: - - Two - - three - name: azure-us - openshiftVersion: 4.10.18 - platform: - azure: - baseDomainResourceGroupName: dojo-dns-zones - region: eastus - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" - name: acm-provision-edge - targetRevision: main - - clusterDeployments: - mySecondCluster: - baseDomain: blueprints.rhecoeng.com - name: aws-cd-two-wo-pool - openshiftVersion: 4.10.18 - platform: - aws: - region: ap-southeast-3 - name: acm-provision-on-deploy - - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" - hostedArgoSites: - - domain: perth1.beekhof.net - name: perth - - domain: syd.beekhof.net - name: sydney - name: argo-edge - name: example - namespaces: - - open-cluster-management: - annotations: - openshift.io/cluster-monitoring: "true" - owner: namespace owner - labels: - kubernetes.io/os: linux - openshift.io/node-selector: "" - - application-ci: - operatorGroup: true - targetNamespaces: - - application-ci - - other-namespace - - exclude-targetns: - operatorGroup: true - targetNamespaces: null - - include-ci - - exclude-og - - totally-exclude-og: - operatorGroup: false - - include-default-og: - operatorGroup: true - nodes: - - m-m00.cluster.example.tld: - labels: - cluster.ocs.openshift.io/openshift-storage: "" - - m-m01.cluster.example.tld: - labels: - cluster.ocs.openshift.io/openshift-storage: "" - - m-m02.cluster.example.tld: - labels: - cluster.ocs.openshift.io/openshift-storage: "" - operatorgroupExcludes: - - exclude-og - projects: - - datacenter - scheduler: - mastersSchedulable: true - sharedValueFiles: - - /values/aws.yaml - - /values/4.12.yaml - subscriptions: - acm: - channel: release-2.4 - csv: advanced-cluster-management.v2.4.1 - name: advanced-cluster-management - namespace: open-cluster-management - odh: - csv: opendatahub-operator.v1.1.0 - disabled: true - name: opendatahub-operator - source: community-operators - pipelines: - csv: redhat-openshift-pipelines.v1.5.2 - name: openshift-pipelines-operator-rh - targetCluster: in-cluster - enabled: all - global: - clusterDomain: region.example.com - clusterPlatform: aws - clusterVersion: "4.12" - extraValueFiles: [] - git: - account: hybrid-cloud-patterns - dev_revision: main - email: someone@somewhere.com - hostname: github.com - hubClusterDomain: apps.hub.example.com - localClusterDomain: apps.region.example.com - multiClusterTarget: all - namespace: pattern-namespace - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Automatic - useCSV: false - pattern: mypattern - repoURL: https://github.com/pattern-clone/mypattern - secretStore: - backend: vault - targetRevision: main - main: - clusterGroupName: example - git: - repoURL: https://github.com/pattern-clone/mypattern - revision: main - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: trusted-ca-bundle - namespace: imperative - annotations: - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/plumbing/trusted-bundle-ca-configmap.yaml -kind: ConfigMap -apiVersion: v1 -metadata: - name: trusted-ca-bundle - namespace: mypattern-example - labels: - config.openshift.io/inject-trusted-cabundle: 'true' ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-admin-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-admin-clusterrolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-admin-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-admin-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: mypattern-example-cluster-admin-rolebinding - # We need to have this before anything else or the sync might get stuck forever - # due to permission issues - annotations: - argocd.argoproj.io/sync-wave: "-100" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: example-gitops-argocd-application-controller - namespace: mypattern-example - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: example-gitops-argocd-server - namespace: mypattern-example - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: example-gitops-argocd-dex-server - namespace: mypattern-example ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/job.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: imperative-cronjob - namespace: imperative -spec: - schedule: "*/10 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: imperative-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: fetch-ca - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; - ls -l /tmp/ca-bundles/ - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - - name: ca-bundles - mountPath: /etc/pki/tls/certs - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - - name: test - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "234" - - ansible-playbook - - -e - - "@/values/values.yaml" - - ansible/test.yml - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - name: ca-bundles - emptyDir: {} - restartPolicy: Never ---- -# Source: clustergroup/templates/imperative/unsealjob.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: imperative -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: fetch-ca - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; - ls -l /tmp/ca-bundles/ - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - - name: ca-bundles - mountPath: /etc/pki/tls/certs - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - - name: unseal-playbook - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - name: ca-bundles - emptyDir: {} - restartPolicy: Never ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- ---- -# Source: clustergroup/templates/core/subscriptions.yaml ---- ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: argo-edge - namespace: openshift-gitops -spec: - description: "Cluster Group argo-edge" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: datacenter - namespace: mypattern-example -spec: - description: "Pattern datacenter" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: acm - namespace: mypattern-example - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: open-cluster-management - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/acm - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-example.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-example.yaml" - - "/values-4.12-example.yaml" - - "/values/aws.yaml" - - "/values/4.12.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - ignoreDifferences: [ - { - "group": "internal.open-cluster-management.io", - "jsonPointers": [ - "/spec/loggingCA" - ], - "kind": "ManagedClusterInfo" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: pipelines - namespace: mypattern-example - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: application-ci - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/pipelines - helm: - ignoreMissingValueFiles: true - values: | - extraParametersNested: - valueFiles: - - "/values-global.yaml" - - "/values-example.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-example.yaml" - - "/values-4.12-example.yaml" - - "/values/aws.yaml" - - "/values/4.12.yaml" - - "/values/4.12/aws.yaml" - parameters: - - name: global.repoURL - value: https://github.com/pattern-clone/mypattern - - name: global.originURL - value: - - name: global.targetRevision - value: main - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.multiSourceSupport - value: - - name: global.multiSourceRepoUrl - value: - - name: global.multiSourceTargetRevision - value: - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.experimentalCapabilities - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: mypattern-argo-edge-perth - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: argo-edge - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-argo-edge.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.perth1.beekhof.net - - name: global.clusterDomain - value: perth1.beekhof.net - - name: enabled - value: core - - name: clusterGroup.name - value: argo-edge - - name: clusterGroup.targetCluster - value: perth - - name: clusterGroup.hostedSite.secretsPath - value: secret/data/hub/cluster_perth - - name: clusterGroup.isHubCluster - value: "false" - destination: - name: perth - namespace: mypattern-argo-edge - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: mypattern-argo-edge-perth-plumbing - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: argo-edge - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-argo-edge.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.perth1.beekhof.net - - name: global.clusterDomain - value: perth1.beekhof.net - - name: enabled - value: plumbing - - name: clusterGroup.name - value: argo-edge - - name: clusterGroup.targetCluster - value: perth - - name: clusterGroup.hostedSite.secretsPath - value: secret/data/hub/cluster_perth - - name: clusterGroup.isHubCluster - value: "false" - destination: - name: in-cluster - namespace: openshift-gitops - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: mypattern-argo-edge-sydney - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: argo-edge - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-argo-edge.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.syd.beekhof.net - - name: global.clusterDomain - value: syd.beekhof.net - - name: enabled - value: core - - name: clusterGroup.name - value: argo-edge - - name: clusterGroup.targetCluster - value: sydney - - name: clusterGroup.hostedSite.secretsPath - value: secret/data/hub/cluster_sydney - - name: clusterGroup.isHubCluster - value: "false" - destination: - name: sydney - namespace: mypattern-argo-edge - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: mypattern-argo-edge-sydney-plumbing - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: argo-edge - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-argo-edge.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.syd.beekhof.net - - name: global.clusterDomain - value: syd.beekhof.net - - name: enabled - value: plumbing - - name: clusterGroup.name - value: argo-edge - - name: clusterGroup.targetCluster - value: sydney - - name: clusterGroup.hostedSite.secretsPath - value: secret/data/hub/cluster_sydney - - name: clusterGroup.isHubCluster - value: "false" - destination: - name: in-cluster - namespace: openshift-gitops - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: example-gitops - namespace: mypattern-example - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - resourceTrackingMethod: label - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - initContainers: - - command: - - bash - - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - name: fetch-ca - resources: {} - volumeMounts: - - mountPath: /var/run/kube-root-ca - name: kube-root-ca - - mountPath: /var/run/trusted-ca - name: trusted-ca-bundle - - mountPath: /var/run/trusted-hub - name: trusted-hub-bundle - - mountPath: /tmp/ca-bundles - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 1Gi - requests: - cpu: 250m - memory: 256Mi - volumeMounts: - - mountPath: /etc/pki/tls/certs - name: ca-bundles - volumes: - - configMap: - name: kube-root-ca.crt - name: kube-root-ca - - configMap: - name: trusted-ca-bundle - optional: true - name: trusted-ca-bundle - - configMap: - name: trusted-hub-bundle - optional: true - name: trusted-hub-bundle - - emptyDir: {} - name: ca-bundles - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: example-gitops-link - namespace: mypattern-example -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://example-gitops-server-mypattern-example.apps.region.example.com' - location: ApplicationMenu - text: 'Example ArgoCD' ---- -# Source: clustergroup/templates/core/nodes.yaml -apiVersion: v1 -kind: Node -metadata: - name: m-m00.cluster.example.tld - labels: - argocd.argoproj.io/managed-by: mypattern-example - cluster.ocs.openshift.io/openshift-storage: "" ---- -# Source: clustergroup/templates/core/nodes.yaml -apiVersion: v1 -kind: Node -metadata: - name: m-m01.cluster.example.tld - labels: - argocd.argoproj.io/managed-by: mypattern-example - cluster.ocs.openshift.io/openshift-storage: "" ---- -# Source: clustergroup/templates/core/nodes.yaml -apiVersion: v1 -kind: Node -metadata: - name: m-m02.cluster.example.tld - labels: - argocd.argoproj.io/managed-by: mypattern-example - cluster.ocs.openshift.io/openshift-storage: "" ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: application-ci-operator-group - namespace: application-ci -spec: - targetNamespaces: - - application-ci - - other-namespace ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: exclude-targetns-operator-group - namespace: exclude-targetns ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: include-ci-operator-group - namespace: include-ci -spec: - targetNamespaces: - - include-ci ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: include-default-og-operator-group - namespace: include-default-og -spec: - targetNamespaces: - - include-default-og ---- -# Source: clustergroup/templates/core/scheduler.yaml -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: - mastersSchedulable: true ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: advanced-cluster-management - namespace: open-cluster-management -spec: - name: advanced-cluster-management - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: release-2.4 - installPlanApproval: Automatic - startingCSV: advanced-cluster-management.v2.4.1 ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-pipelines-operator-rh - namespace: openshift-operators -spec: - name: openshift-pipelines-operator-rh - source: redhat-operators - sourceNamespace: openshift-marketplace - installPlanApproval: Automatic - startingCSV: redhat-openshift-pipelines.v1.5.2 diff --git a/tests/clustergroup.expected.diff b/tests/clustergroup.expected.diff deleted file mode 100644 index c2fba541..00000000 --- a/tests/clustergroup.expected.diff +++ /dev/null @@ -1,381 +0,0 @@ ---- -# Source: pattern-clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: common-example - name: imperative ---- -# Source: pattern-clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: common-example - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: common-example -spec: {} ---- -# Source: pattern-clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: pattern-clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-example - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: [] - imperative: - activeDeadlineSeconds: 3600 - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-22/ee-supported-rhel8:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: [] - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: true - managedClusterGroups: [] - name: example - namespaces: [] - projects: [] - subscriptions: [] - targetCluster: in-cluster - enabled: all - global: - options: - installPlanApproval: Automatic - syncPolicy: Automatic - useCSV: true - pattern: common - targetRevision: main - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: pattern-clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: pattern-clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: pattern-clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: pattern-clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-example-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: example-gitops-argocd-application-controller - namespace: common-example - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: example-gitops-argocd-server - namespace: common-example - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: example-gitops-argocd-dex-server - namespace: common-example ---- -# Source: pattern-clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: pattern-clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-admin-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: pattern-clustergroup/templates/imperative/unsealjob.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: imperative -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: git-init - image: registry.redhat.io/ansible-automation-platform-22/ee-supported-rhel8:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - "mkdir /git/{repo,home};git clone --single-branch --branch main --depth 1 -- /git/repo;chmod 0770 /git/{repo,home}" - volumeMounts: - - name: git - mountPath: "/git" - - name: unseal-playbook - image: registry.redhat.io/ansible-automation-platform-22/ee-supported-rhel8:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-22/ee-supported-rhel8:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example - restartPolicy: Never ---- -# Source: pattern-clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: example-gitops - namespace: common-example - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - applicationInstanceLabelKey: argocd.argoproj.io/instance - # Not the greatest way to pass git/quay info to sub-applications, but it will do until - # we can support helmChart with kustomize - # The other option is to pass them in as environment variables eg. BLUEPRINT_VERSION - configManagementPlugins: | - - name: kustomize-version - generate: - command: ["sh", "-c"] - args: ["kustomize version 1>&2 && exit 1"] - - name: kustomize-with-helm - generate: - command: ["kustomize"] - args: ["build", "--enable-helm"] - - name: helm-with-kustomize - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-example.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern=common - --set global.clusterDomain= - --set global.hubClusterDomain= - --set global.localClusterDomain= - --set clusterGroup.name=example - --post-renderer ./kustomize"] - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: pattern-clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: example-gitops-link - namespace: common-example -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://example-gitops-server-common-example.' - location: ApplicationMenu - text: 'Example ArgoCD' diff --git a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml deleted file mode 100644 index fea780d3..00000000 --- a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,13143 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: |- - The labels to select by to find the Namespaces to create the ExternalSecrets in. - Deprecated: Use NamespaceSelectors instead. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelectors: - description: A list of labels to select by to find the Namespaces to create the ExternalSecrets in. The selectors are ORed. - items: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: array - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/githubaccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: githubaccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - githubaccesstoken - kind: GithubAccessToken - listKind: GithubAccessTokenList - plural: githubaccesstokens - shortNames: - - githubaccesstoken - singular: githubaccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: GithubAccessToken generates ghs_ accessToken - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - appID: - type: string - auth: - description: Auth configures how ESO authenticates with a Github instance. - properties: - privateKey: - properties: - secretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - secretRef - type: object - required: - - privateKey - type: object - installID: - type: string - url: - description: URL configures the Github instance URL. Defaults to https://github.com/. - type: string - required: - - appID - - auth - - installID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - updatePolicy: - default: Replace - description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' - enum: - - Replace - - IfNotExists - type: string - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: |- - Synced PushSecrets, including secrets that already exist in provider. - Matches secret stores to PushSecretData that was stored to that secret store. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-controller -subjects: - - name: golang-external-secrets - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: golang-external-secrets - namespace: default ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - - --enable-partial-cache=true - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - dnsPolicy: ClusterFirst ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.apps.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: Secret - name: hub-ca - key: hub-kube-root-ca.crt - namespace: golang-external-secrets - - auth: - kubernetes: - - mountPath: region.example.com - role: region.example.com-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml b/tests/golang-external-secrets-industrial-edge-hub.expected.yaml deleted file mode 100644 index 341ae7e2..00000000 --- a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,13143 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: |- - The labels to select by to find the Namespaces to create the ExternalSecrets in. - Deprecated: Use NamespaceSelectors instead. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelectors: - description: A list of labels to select by to find the Namespaces to create the ExternalSecrets in. The selectors are ORed. - items: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: array - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/githubaccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: githubaccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - githubaccesstoken - kind: GithubAccessToken - listKind: GithubAccessTokenList - plural: githubaccesstokens - shortNames: - - githubaccesstoken - singular: githubaccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: GithubAccessToken generates ghs_ accessToken - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - appID: - type: string - auth: - description: Auth configures how ESO authenticates with a Github instance. - properties: - privateKey: - properties: - secretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - secretRef - type: object - required: - - privateKey - type: object - installID: - type: string - url: - description: URL configures the Github instance URL. Defaults to https://github.com/. - type: string - required: - - appID - - auth - - installID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - updatePolicy: - default: Replace - description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' - enum: - - Replace - - IfNotExists - type: string - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: |- - Synced PushSecrets, including secrets that already exist in provider. - Matches secret stores to PushSecretData that was stored to that secret store. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-controller -subjects: - - name: golang-external-secrets - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: golang-external-secrets - namespace: default ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - - --enable-partial-cache=true - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - dnsPolicy: ClusterFirst ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.apps.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: ConfigMap - name: kube-root-ca.crt - key: ca.crt - namespace: golang-external-secrets - - auth: - kubernetes: - - mountPath: hub - role: hub-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml b/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index 341ae7e2..00000000 --- a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,13143 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: |- - The labels to select by to find the Namespaces to create the ExternalSecrets in. - Deprecated: Use NamespaceSelectors instead. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelectors: - description: A list of labels to select by to find the Namespaces to create the ExternalSecrets in. The selectors are ORed. - items: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: array - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/githubaccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: githubaccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - githubaccesstoken - kind: GithubAccessToken - listKind: GithubAccessTokenList - plural: githubaccesstokens - shortNames: - - githubaccesstoken - singular: githubaccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: GithubAccessToken generates ghs_ accessToken - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - appID: - type: string - auth: - description: Auth configures how ESO authenticates with a Github instance. - properties: - privateKey: - properties: - secretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - secretRef - type: object - required: - - privateKey - type: object - installID: - type: string - url: - description: URL configures the Github instance URL. Defaults to https://github.com/. - type: string - required: - - appID - - auth - - installID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - updatePolicy: - default: Replace - description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' - enum: - - Replace - - IfNotExists - type: string - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: |- - Synced PushSecrets, including secrets that already exist in provider. - Matches secret stores to PushSecretData that was stored to that secret store. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-controller -subjects: - - name: golang-external-secrets - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: golang-external-secrets - namespace: default ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - - --enable-partial-cache=true - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - dnsPolicy: ClusterFirst ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.apps.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: ConfigMap - name: kube-root-ca.crt - key: ca.crt - namespace: golang-external-secrets - - auth: - kubernetes: - - mountPath: hub - role: hub-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/golang-external-secrets-naked.expected.yaml b/tests/golang-external-secrets-naked.expected.yaml deleted file mode 100644 index 72ffed42..00000000 --- a/tests/golang-external-secrets-naked.expected.yaml +++ /dev/null @@ -1,13143 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: |- - The labels to select by to find the Namespaces to create the ExternalSecrets in. - Deprecated: Use NamespaceSelectors instead. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelectors: - description: A list of labels to select by to find the Namespaces to create the ExternalSecrets in. The selectors are ORed. - items: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: array - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/githubaccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: githubaccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - githubaccesstoken - kind: GithubAccessToken - listKind: GithubAccessTokenList - plural: githubaccesstokens - shortNames: - - githubaccesstoken - singular: githubaccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: GithubAccessToken generates ghs_ accessToken - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - appID: - type: string - auth: - description: Auth configures how ESO authenticates with a Github instance. - properties: - privateKey: - properties: - secretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - secretRef - type: object - required: - - privateKey - type: object - installID: - type: string - url: - description: URL configures the Github instance URL. Defaults to https://github.com/. - type: string - required: - - appID - - auth - - installID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - updatePolicy: - default: Replace - description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' - enum: - - Replace - - IfNotExists - type: string - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: |- - Synced PushSecrets, including secrets that already exist in provider. - Matches secret stores to PushSecretData that was stored to that secret store. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-controller -subjects: - - name: golang-external-secrets - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: golang-external-secrets - namespace: default ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - - --enable-partial-cache=true - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - dnsPolicy: ClusterFirst ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: ConfigMap - name: kube-root-ca.crt - key: ca.crt - namespace: golang-external-secrets - - auth: - kubernetes: - - mountPath: hub - role: hub-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/golang-external-secrets-normal.expected.yaml b/tests/golang-external-secrets-normal.expected.yaml deleted file mode 100644 index 341ae7e2..00000000 --- a/tests/golang-external-secrets-normal.expected.yaml +++ /dev/null @@ -1,13143 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: |- - The labels to select by to find the Namespaces to create the ExternalSecrets in. - Deprecated: Use NamespaceSelectors instead. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelectors: - description: A list of labels to select by to find the Namespaces to create the ExternalSecrets in. The selectors are ORed. - items: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: array - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/githubaccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: githubaccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - githubaccesstoken - kind: GithubAccessToken - listKind: GithubAccessTokenList - plural: githubaccesstokens - shortNames: - - githubaccesstoken - singular: githubaccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: GithubAccessToken generates ghs_ accessToken - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - appID: - type: string - auth: - description: Auth configures how ESO authenticates with a Github instance. - properties: - privateKey: - properties: - secretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - secretRef - type: object - required: - - privateKey - type: object - installID: - type: string - url: - description: URL configures the Github instance URL. Defaults to https://github.com/. - type: string - required: - - appID - - auth - - installID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - updatePolicy: - default: Replace - description: 'UpdatePolicy to handle Secrets in the provider. Possible Values: "Replace/IfNotExists". Defaults to "Replace".' - enum: - - Replace - - IfNotExists - type: string - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - conversionStrategy: - default: None - description: Used to define a conversion Strategy for the secret keys - enum: - - None - - ReverseUnicode - type: string - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: |- - Synced PushSecrets, including secrets that already exist in provider. - Matches secret stores to PushSecretData that was stored to that secret store. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceRegexes: - description: Choose namespaces by using regex matching - items: - type: string - type: array - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - prefix: - description: Prefix adds a prefix to all retrieved values. - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - properties: - clientCertificate: - description: The Azure ClientCertificate of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientId: - description: The Azure clientId of the service principle or managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - tenantId: - description: The Azure tenantId of the managed identity used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - bitwardensecretsmanager: - description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider - properties: - apiURL: - type: string - auth: - description: |- - Auth configures how secret-manager authenticates with a bitwarden machine account instance. - Make sure that the token being used has permissions on the given secret. - properties: - secretRef: - description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. - properties: - credentials: - description: AccessToken used for the bitwarden instance. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - credentials - type: object - required: - - secretRef - type: object - bitwardenServerSDKURL: - type: string - caBundle: - description: |- - Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack - can be performed. - type: string - identityURL: - type: string - organizationID: - description: OrganizationID determines which organization this secret store manages. - type: string - projectID: - description: ProjectID determines which project this secret store manages. - type: string - required: - - auth - - caBundle - - organizationID - - projectID - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - hostId: - description: |- - Optional HostID for JWT authentication. This may be used depending - on how the Conjur JWT authenticator policy is configured. - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - device42: - description: Device42 configures this store to sync secrets using the Device42 provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Device42 instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - host: - description: URL configures the Device42 instance URL. - type: string - required: - - auth - - host - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - fortanix: - description: Fortanix configures this store to sync secrets using the Fortanix provider - properties: - apiKey: - description: APIKey is the API token to access SDKMS Applications. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the SDKMS API Key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - description: APIURL is the URL of SDKMS API. Defaults to `sdkms.fortanix.com`. - type: string - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - location: - description: Location optionally defines a location for a secret - type: string - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - infisical: - description: Infisical configures this store to sync secrets using the Infisical provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Infisical API - properties: - universalAuthCredentials: - properties: - clientId: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecret - type: object - type: object - hostAPI: - default: https://app.infisical.com/api - type: string - secretsScope: - properties: - environmentSlug: - type: string - projectSlug: - type: string - secretsPath: - default: / - type: string - required: - - environmentSlug - - projectSlug - type: object - required: - - auth - - secretsScope - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - authRef: - description: A reference to a secret that contains the auth information. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - type: object - onboardbase: - description: Onboardbase configures this store to sync secrets using the Onboardbase provider - properties: - apiHost: - default: https://public.onboardbase.com/api/v1/ - description: APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/ - type: string - auth: - description: Auth configures how the Operator authenticates with the Onboardbase API - properties: - apiKeyRef: - description: |- - OnboardbaseAPIKey is the APIKey generated by an admin account. - It is used to recognize and authorize access to a project and environment within onboardbase - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - passcodeRef: - description: OnboardbasePasscode is the passcode attached to the API Key - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - apiKeyRef - - passcodeRef - type: object - environment: - default: development - description: Environment is the name of an environmnent within a project to pull the secrets from - type: string - project: - default: development - description: Project is an onboardbase project that the secrets should be pulled from - type: string - required: - - apiHost - - auth - - environment - - project - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - passbolt: - properties: - auth: - description: Auth defines the information necessary to authenticate against Passbolt Server - properties: - passwordSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privateKeySecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - passwordSecretRef - - privateKeySecretRef - type: object - host: - description: Host defines the Passbolt Server to connect to - type: string - required: - - auth - - host - type: object - passworddepot: - description: Configures a store to sync secrets with a Password Depot instance. - properties: - auth: - description: Auth configures how secret-manager authenticates with a Password Depot instance. - properties: - secretRef: - properties: - credentials: - description: Username / Password is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - database: - description: Database to use as source - type: string - host: - description: URL configures the Password Depot instance URL. - type: string - required: - - auth - - database - - host - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com/api/preview - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - secretserver: - description: |- - SecretServer configures this store to sync secrets using SecretServer provider - https://docs.delinea.com/online-help/secret-server/start.htm - properties: - password: - description: Password is the secret server account password. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - serverURL: - description: |- - ServerURL - URL to your secret server installation - type: string - username: - description: Username is the secret server account username. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - password - - serverURL - - username - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - namespace: - description: |- - Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. - Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - This will default to Vault.Namespace field if set, or empty otherwise - type: string - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - headers: - additionalProperties: - type: string - description: Headers to be added in Vault request - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - labels: - external-secrets.io/component: controller - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "githubaccesstokens" - - "passwords" - - "vaultdynamicsecrets" - - "webhooks" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: golang-external-secrets-controller -subjects: - - name: golang-external-secrets - namespace: default - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: golang-external-secrets-leaderelection - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: golang-external-secrets - namespace: default ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-cert-controller - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - - --enable-partial-cache=true - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - dnsPolicy: ClusterFirst ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: golang-external-secrets-webhook - namespace: default - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.10.0 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.10.0" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.10.0-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - --loglevel=info - - --zap-time-encoding=epoch - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.apps.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: ConfigMap - name: kube-root-ca.crt - key: ca.crt - namespace: golang-external-secrets - - auth: - kubernetes: - - mountPath: hub - role: hub-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: default - name: golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/golang-external-secrets.expected.diff b/tests/golang-external-secrets.expected.diff deleted file mode 100644 index 19d26594..00000000 --- a/tests/golang-external-secrets.expected.diff +++ /dev/null @@ -1,11 +0,0 @@ ---- tests/golang-external-secrets-naked.expected.yaml -+++ tests/golang-external-secrets-normal.expected.yaml -@@ -6337,7 +6337,7 @@ - spec: - provider: - vault: -- server: https://vault-vault.hub.example.com -+ server: https://vault-vault.apps.hub.example.com - path: secret - # Version of KV backend - version: v2 diff --git a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml deleted file mode 100644 index fb8f1c8e..00000000 --- a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,410 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hashicorp-vault-config - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: hashicorp-vault - namespace: pattern-namespace ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-internal - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-ui - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - annotations: - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: hashicorp-vault - - volumes: - - - name: config - configMap: - name: hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.region.example.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: hashicorp-vault-server-test - namespace: pattern-namespace - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://hashicorp-vault.pattern-namespace.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml deleted file mode 100644 index fb8f1c8e..00000000 --- a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,410 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hashicorp-vault-config - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: hashicorp-vault - namespace: pattern-namespace ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-internal - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-ui - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - annotations: - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: hashicorp-vault - - volumes: - - - name: config - configMap: - name: hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.region.example.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: hashicorp-vault-server-test - namespace: pattern-namespace - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://hashicorp-vault.pattern-namespace.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index fb8f1c8e..00000000 --- a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,410 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hashicorp-vault-config - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: hashicorp-vault - namespace: pattern-namespace ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-internal - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-ui - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - annotations: - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: hashicorp-vault - - volumes: - - - name: config - configMap: - name: hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.region.example.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: hashicorp-vault-server-test - namespace: pattern-namespace - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://hashicorp-vault.pattern-namespace.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/hashicorp-vault-naked.expected.yaml b/tests/hashicorp-vault-naked.expected.yaml deleted file mode 100644 index 49ea96cb..00000000 --- a/tests/hashicorp-vault-naked.expected.yaml +++ /dev/null @@ -1,410 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: hashicorp-vault - namespace: default - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hashicorp-vault-config - namespace: default - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: hashicorp-vault - namespace: default ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-internal - namespace: default - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault - namespace: default - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-ui - namespace: default - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: hashicorp-vault - namespace: default - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - annotations: - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: hashicorp-vault - - volumes: - - - name: config - configMap: - name: hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.foo.cluster.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: hashicorp-vault - namespace: default - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: hashicorp-vault-server-test - namespace: default - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://hashicorp-vault.default.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/hashicorp-vault-normal.expected.yaml b/tests/hashicorp-vault-normal.expected.yaml deleted file mode 100644 index fb8f1c8e..00000000 --- a/tests/hashicorp-vault-normal.expected.yaml +++ /dev/null @@ -1,410 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hashicorp-vault-config - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: hashicorp-vault - namespace: pattern-namespace ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-internal - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: hashicorp-vault-ui - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - component: server - annotations: - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: hashicorp-vault - - volumes: - - - name: config - configMap: - name: hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.region.example.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.28.1 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: hashicorp-vault-server-test - namespace: pattern-namespace - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.17.3-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://hashicorp-vault.pattern-namespace.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/hashicorp-vault.expected.diff b/tests/hashicorp-vault.expected.diff deleted file mode 100644 index 9e948a07..00000000 --- a/tests/hashicorp-vault.expected.diff +++ /dev/null @@ -1,11 +0,0 @@ ---- tests/hashicorp-vault-naked.expected.yaml -+++ tests/hashicorp-vault-normal.expected.yaml -@@ -341,7 +341,7 @@ - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 -- href: 'https://vault-vault.apps.foo.cluster.com' -+ href: 'https://vault-vault.apps.region.example.com' - location: ApplicationMenu - text: 'Vault' - --- diff --git a/tests/install-industrial-edge-factory.expected.yaml b/tests/install-industrial-edge-factory.expected.yaml deleted file mode 100644 index 0dfd0d84..00000000 --- a/tests/install-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Source: pattern-install/templates/argocd/namespace.yaml -# Pre-create so we can create our argo app for keeping subscriptions in sync -# Do it here so that we don't try to sync it in the future -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-gitops ---- -# Source: pattern-install/templates/argocd/application.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: install-example - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: install-example - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-example.yaml" - # Track the progress of https://github.com/argoproj/argo-cd/pull/6280 - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: install - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.clusterVersion - value: "" - syncPolicy: - automated: {} ---- -# Source: pattern-install/templates/argocd/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: "" -spec: - channel: stable - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: install-example,openshift-gitops diff --git a/tests/install-industrial-edge-hub.expected.yaml b/tests/install-industrial-edge-hub.expected.yaml deleted file mode 100644 index 0dfd0d84..00000000 --- a/tests/install-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Source: pattern-install/templates/argocd/namespace.yaml -# Pre-create so we can create our argo app for keeping subscriptions in sync -# Do it here so that we don't try to sync it in the future -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-gitops ---- -# Source: pattern-install/templates/argocd/application.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: install-example - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: install-example - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-example.yaml" - # Track the progress of https://github.com/argoproj/argo-cd/pull/6280 - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: install - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.clusterVersion - value: "" - syncPolicy: - automated: {} ---- -# Source: pattern-install/templates/argocd/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: "" -spec: - channel: stable - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: install-example,openshift-gitops diff --git a/tests/install-medical-diagnosis-hub.expected.yaml b/tests/install-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index 0dfd0d84..00000000 --- a/tests/install-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Source: pattern-install/templates/argocd/namespace.yaml -# Pre-create so we can create our argo app for keeping subscriptions in sync -# Do it here so that we don't try to sync it in the future -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-gitops ---- -# Source: pattern-install/templates/argocd/application.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: install-example - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: install-example - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-example.yaml" - # Track the progress of https://github.com/argoproj/argo-cd/pull/6280 - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: install - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.clusterVersion - value: "" - syncPolicy: - automated: {} ---- -# Source: pattern-install/templates/argocd/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: "" -spec: - channel: stable - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: install-example,openshift-gitops diff --git a/tests/letsencrypt-industrial-edge-factory.expected.yaml b/tests/letsencrypt-industrial-edge-factory.expected.yaml deleted file mode 100644 index b5aded2f..00000000 --- a/tests/letsencrypt-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.region.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.region.example.com' - usages: - - server auth - dnsNames: - - api.region.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.region.example.com' - usages: - - server auth - dnsNames: - - '*.apps.region.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/letsencrypt-industrial-edge-hub.expected.yaml b/tests/letsencrypt-industrial-edge-hub.expected.yaml deleted file mode 100644 index b5aded2f..00000000 --- a/tests/letsencrypt-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.region.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.region.example.com' - usages: - - server auth - dnsNames: - - api.region.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.region.example.com' - usages: - - server auth - dnsNames: - - '*.apps.region.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/letsencrypt-medical-diagnosis-hub.expected.yaml b/tests/letsencrypt-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index b5aded2f..00000000 --- a/tests/letsencrypt-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.region.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.region.example.com' - usages: - - server auth - dnsNames: - - api.region.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.region.example.com' - usages: - - server auth - dnsNames: - - '*.apps.region.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/letsencrypt-naked.expected.yaml b/tests/letsencrypt-naked.expected.yaml deleted file mode 100644 index 73aa94a4..00000000 --- a/tests/letsencrypt-naked.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.example.com' - usages: - - server auth - dnsNames: - - api.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.example.com' - usages: - - server auth - dnsNames: - - '*.apps.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/letsencrypt-normal.expected.yaml b/tests/letsencrypt-normal.expected.yaml deleted file mode 100644 index b5aded2f..00000000 --- a/tests/letsencrypt-normal.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.region.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.region.example.com' - usages: - - server auth - dnsNames: - - api.region.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.region.example.com' - usages: - - server auth - dnsNames: - - '*.apps.region.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/operator-install-industrial-edge-factory.expected.yaml b/tests/operator-install-industrial-edge-factory.expected.yaml deleted file mode 100644 index 2bb7854e..00000000 --- a/tests/operator-install-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.13 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: operator-install - namespace: openshift-operators -spec: - clusterGroupName: example - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - multiSourceConfig: - enabled: false ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace diff --git a/tests/operator-install-industrial-edge-hub.expected.yaml b/tests/operator-install-industrial-edge-hub.expected.yaml deleted file mode 100644 index 2bb7854e..00000000 --- a/tests/operator-install-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.13 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: operator-install - namespace: openshift-operators -spec: - clusterGroupName: example - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - multiSourceConfig: - enabled: false ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace diff --git a/tests/operator-install-medical-diagnosis-hub.expected.yaml b/tests/operator-install-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index 2bb7854e..00000000 --- a/tests/operator-install-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.13 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: operator-install - namespace: openshift-operators -spec: - clusterGroupName: example - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - multiSourceConfig: - enabled: false ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace diff --git a/tests/operator-install-naked.expected.yaml b/tests/operator-install-naked.expected.yaml deleted file mode 100644 index d5f75c80..00000000 --- a/tests/operator-install-naked.expected.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.13 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: operator-install - namespace: openshift-operators -spec: - clusterGroupName: default - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - multiSourceConfig: - enabled: false ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace diff --git a/tests/operator-install-normal.expected.yaml b/tests/operator-install-normal.expected.yaml deleted file mode 100644 index 2bb7854e..00000000 --- a/tests/operator-install-normal.expected.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.13 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: operator-install - namespace: openshift-operators -spec: - clusterGroupName: example - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - multiSourceConfig: - enabled: false ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace diff --git a/tests/operator-install.expected.diff b/tests/operator-install.expected.diff deleted file mode 100644 index 3f73da90..00000000 --- a/tests/operator-install.expected.diff +++ /dev/null @@ -1,11 +0,0 @@ ---- tests/operator-install-naked.expected.yaml -+++ tests/operator-install-normal.expected.yaml -@@ -6,7 +6,7 @@ - name: operator-install - namespace: openshift-operators - spec: -- clusterGroupName: default -+ clusterGroupName: example - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main From ce6afef625e494088bcd1207fbb4cbded2a56026 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 13 Sep 2024 15:10:08 +0200 Subject: [PATCH 172/222] Drop the json schema checking job It only makes sense in the presence of helm charts. We should prolly move it to each chart repo. --- .github/workflows/jsonschema.yaml | 57 ------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 .github/workflows/jsonschema.yaml diff --git a/.github/workflows/jsonschema.yaml b/.github/workflows/jsonschema.yaml deleted file mode 100644 index e47de928..00000000 --- a/.github/workflows/jsonschema.yaml +++ /dev/null @@ -1,57 +0,0 @@ ---- -name: Verify json schema - -# -# Documentation: -# https://help.github.com/en/articles/workflow-syntax-for-github-actions -# - -############################# -# Start the job on all push # -############################# -on: [push, pull_request] - -############### -# Set the Job # -############### -jobs: - jsonschema_tests: - # Name the Job - name: Json Schema tests - strategy: - matrix: - python-version: [3.11.3] - # Set the agent to run on - runs-on: ubuntu-latest - - ################## - # Load all steps # - ################## - steps: - ########################## - # Checkout the code base # - ########################## - - name: Checkout Code - uses: actions/checkout@v4 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install check-jsonschema - - - name: Verify secrets json schema - run: | - check-jsonschema --schemafile ./ansible/roles/vault_utils/values-secrets.v1.schema.json examples/secrets/values-secret.v1.yaml - check-jsonschema --schemafile ./ansible/roles/vault_utils/values-secrets.v2.schema.json examples/secrets/values-secret.v2.yaml - - - name: Verify ClusterGroup values.schema.json - run: | - set -e; for i in examples/*yaml; do echo "$i"; check-jsonschema --schemafile ./clustergroup/values.schema.json "$i"; done From eb58b8b3cbbf55e6113845a8a9198045d3010d39 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 13 Sep 2024 10:40:48 +0200 Subject: [PATCH 173/222] Add a README note on the main branch --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 568a2396..095b751c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,13 @@ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +## Note + +This is the `main` branch of common and it assumes that the pattern is fully +multisource (meaning that any used charts from VP is actually referenced from +either a helm chart repository or quay repository). I.e. there are no helm +charts contained in this branch of common. + ## Start Here This repository is never used as standalone. It is usually imported in each pattern as a subtree. From c37f4543147e7e088a35b325c165eb62a40631c3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 14 Sep 2024 18:20:21 +0200 Subject: [PATCH 174/222] Add a check to see if multisource for clustergroup is enabled Without this in your values-global.yaml files, the deployment with a slimmed down common would fail as follows: - lastTransitionTime: "2024-09-13T18:30:19Z" message: 'Failed to load target state: failed to generate manifest for source 1 of 1: rpc error: code = Unknown desc = Manifest generation error (cached): common/clustergroup: app path does not exist' --- scripts/pattern-util.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index cb7fc873..817b2dac 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -8,6 +8,18 @@ function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' } +function check_for_clustergroup_multisource { + if [ -f values-global.yaml ]; then + # Query .main.multiSourceConfig.enabled and assume it is false if not set + OUT=$(yq -r '.main.multiSourceConfig.enabled // (.main.multiSourceConfig.enabled = "false")') + if [ "${OUT,,}" = "false" ]; then + echo "You must set `.main.multiSourceConfig.enabled: true` in your 'values-global.yaml' file" + echo "because your common subfolder is the slimmed down version with no helm charts in it" + exit 1 + fi + fi +} + if [ -z "$PATTERN_UTILITY_CONTAINER" ]; then PATTERN_UTILITY_CONTAINER="quay.io/hybridcloudpatterns/utility-container" fi @@ -66,6 +78,10 @@ else PKI_HOST_MOUNT_ARGS="" fi +# In the slimmed down common branch we need to check that multisource is enabled for the clustergroup +# chart +check_for_clustergroup_multisource + # Copy Kubeconfig from current environment. The utilities will pick up ~/.kube/config if set so it's not mandatory # $HOME is mounted as itself for any files that are referenced with absolute paths # $HOME is mounted to /root because the UID in the container is 0 and that's where SSH looks for credentials From 241479674e8a5a857ed4a6b36bb0208a48c8b414 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 16 Sep 2024 08:24:15 +0200 Subject: [PATCH 175/222] Move the common slim + multisource test into Makefile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way yq is not required on the host. Tested as follows: * No value set (assumes default is false) ❯ cat values-global.yaml --- global: pattern: multicloud-gitops options: useCSV: false syncPolicy: Automatic installPlanApproval: Automatic main: clusterGroupName: hub # multiSourceConfig: # enabled: true ❯ ./pattern.sh make validate-prereq make -f common/Makefile validate-prereq make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' You must set ".main.multiSourceConfig.enabled: true" in your 'values-global.yaml' file because your common subfolder is the slimmed down version with no helm charts in it make[1]: *** [common/Makefile:161: validate-prereq] Error 1 make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make: *** [Makefile:12: validate-prereq] Error 2 * Value set to false ❯ cat values-global.yaml --- global: pattern: multicloud-gitops options: useCSV: false syncPolicy: Automatic installPlanApproval: Automatic main: clusterGroupName: hub multiSourceConfig: enabled: false ❯ ./pattern.sh make validate-prereq make -f common/Makefile validate-prereq make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' You must set ".main.multiSourceConfig.enabled: true" in your 'values-global.yaml' file because your common subfolder is the slimmed down version with no helm charts in it make[1]: *** [common/Makefile:161: validate-prereq] Error 1 make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make: *** [Makefile:12: validate-prereq] Error 2 * Value set to true ❯ cat values-global.yaml --- global: pattern: multicloud-gitops options: useCSV: false syncPolicy: Automatic installPlanApproval: Automatic main: clusterGroupName: hub multiSourceConfig: enabled: true ❯ ./pattern.sh make validate-prereq make -f common/Makefile validate-prereq make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' --- Makefile | 9 ++++++++- scripts/pattern-util.sh | 16 ---------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index ca1edf06..3f2ba7a4 100644 --- a/Makefile +++ b/Makefile @@ -169,7 +169,14 @@ validate-prereq: ## verify pre-requisites if ! ansible-galaxy collection list | grep kubernetes.core > /dev/null 2>&1; then echo "Not found"; exit 1; fi;\ echo "OK";\ else\ - echo "Skipping prerequisites check as we're running inside a container";\ + if [ -f values-global.yaml ]; then\ + OUT=`yq -r '.main.multiSourceConfig.enabled // (.main.multiSourceConfig.enabled = "false")' values-global.yaml`;\ + if [ "$${OUT,,}" = "false" ]; then\ + echo "You must set \".main.multiSourceConfig.enabled: true\" in your 'values-global.yaml' file";\ + echo "because your common subfolder is the slimmed down version with no helm charts in it";\ + exit 1;\ + fi;\ + fi;\ fi .PHONY: argo-healthcheck diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 817b2dac..cb7fc873 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -8,18 +8,6 @@ function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' } -function check_for_clustergroup_multisource { - if [ -f values-global.yaml ]; then - # Query .main.multiSourceConfig.enabled and assume it is false if not set - OUT=$(yq -r '.main.multiSourceConfig.enabled // (.main.multiSourceConfig.enabled = "false")') - if [ "${OUT,,}" = "false" ]; then - echo "You must set `.main.multiSourceConfig.enabled: true` in your 'values-global.yaml' file" - echo "because your common subfolder is the slimmed down version with no helm charts in it" - exit 1 - fi - fi -} - if [ -z "$PATTERN_UTILITY_CONTAINER" ]; then PATTERN_UTILITY_CONTAINER="quay.io/hybridcloudpatterns/utility-container" fi @@ -78,10 +66,6 @@ else PKI_HOST_MOUNT_ARGS="" fi -# In the slimmed down common branch we need to check that multisource is enabled for the clustergroup -# chart -check_for_clustergroup_multisource - # Copy Kubeconfig from current environment. The utilities will pick up ~/.kube/config if set so it's not mandatory # $HOME is mounted as itself for any files that are referenced with absolute paths # $HOME is mounted to /root because the UID in the container is 0 and that's where SSH looks for credentials From 26f0d47b7c79223f1a747c80e3ff3b14f792c7dd Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 16 Sep 2024 09:00:37 +0200 Subject: [PATCH 176/222] Drop last bit of operator-install and the common symlink --- common | 1 - .../.github/workflows/update-helm-repo.yml | 30 ------------------- 2 files changed, 31 deletions(-) delete mode 120000 common delete mode 100644 operator-install/.github/workflows/update-helm-repo.yml diff --git a/common b/common deleted file mode 120000 index 945c9b46..00000000 --- a/common +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/operator-install/.github/workflows/update-helm-repo.yml b/operator-install/.github/workflows/update-helm-repo.yml deleted file mode 100644 index fa1d6247..00000000 --- a/operator-install/.github/workflows/update-helm-repo.yml +++ /dev/null @@ -1,30 +0,0 @@ -# This invokes the workflow named 'publish-charts' in the umbrella repo -# It expects to have a secret called CHARTS_REPOS_TOKEN which contains -# the GitHub token that has permissions to invoke workflows and commit code -# inside the umbrella-repo. -# The following fine-grained permissions were used in testing and were limited -# to the umbrella repo only: -# - Actions: r/w -# - Commit statuses: r/w -# - Contents: r/w -# - Deployments: r/w -# - Pages: r/w -# - -name: vp-patterns/update-helm-repo -on: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - -jobs: - helmlint: - uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: - contents: read - - update-helm-repo: - needs: [helmlint] - uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@985ba37e0eb50b1b35ec194fc999eae2d0ae1486 - permissions: read-all - secrets: inherit From 9843d9c23f2e22bb3ffc3fc37ef9e7d9a597a74a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 16 Sep 2024 09:06:02 +0200 Subject: [PATCH 177/222] Drop reference-output.yaml as it makes little sense in the slimmed common --- reference-output.yaml | 119 ------------------------------------------ 1 file changed, 119 deletions(-) delete mode 100644 reference-output.yaml diff --git a/reference-output.yaml b/reference-output.yaml deleted file mode 100644 index 1eef9745..00000000 --- a/reference-output.yaml +++ /dev/null @@ -1,119 +0,0 @@ ---- -# Source: pattern-install/templates/argocd/namespace.yaml -# Pre-create so we can create our argo app for keeping subscriptions in sync -# Do it here so that we don't try to sync it in the future -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-gitops ---- -# Source: pattern-install/templates/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: manuela-ci - labels: - manuela-role: pipeline - app.kubernetes.io/instance: manuela ---- -# Source: pattern-install/templates/pipeline/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: pipeline - namespace: manuela-ci -secrets: -- name: git-repo-credentials -- name: image-registry-credentials ---- -# Source: pattern-install/templates/secrets/s3-secret.yaml -kind: Secret -apiVersion: v1 -metadata: - name: s3-secret -type: Opaque -data: - # Pre-create as part of the initial 'helm install' chart - # Create a file with the following: - # s3.accessKey: KEY - # s3.secretKey: secret key - #application.properties: base64 encrypted value of the above file - # This should live in the values-secret.yaml file - application.properties: BASE64STRING ---- -# Source: pattern-install/templates/secrets/secret-git-repo-credentials.yaml -apiVersion: v1 -kind: Secret -metadata: - name: git-repo-credentials - namespace: manuela-ci - annotations: - # Tekton magic, see https://tekton.dev/vault/pipelines-v0.15.2/auth/ - tekton.dev/git-0: https://github.com/hybrid-cloud-patterns -type: kubernetes.io/basic-auth -stringData: - username: STRING - password: STRING ---- -# Source: pattern-install/templates/secrets/secret-image-registry-credentials.yaml -apiVersion: v1 -kind: Secret -metadata: - name: openshift-registry-credentials - namespace: manuela-ci - annotations: - # Tekton magic, see https://tekton.dev/vault/pipelines-v0.15.2/auth/ - tekton.dev/docker-0: "https://" -type: kubernetes.io/basic-auth -stringData: - username: STRING - password: STRING ---- -# Source: pattern-install/templates/argocd/application.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: common-example - namespace: openshift-gitops -spec: - destination: - name: in-cluster - namespace: common-example - project: default - source: - repoURL: https://github.com/beekhof/common.git - targetRevision: main - path: common/clustergroup - helm: - valueFiles: - - "https://github.com/beekhof/patterns/raw/main/values-global.yaml" - - "https://github.com/beekhof/patterns/raw/main/values-example.yaml" - # Track the progress of https://github.com/argoproj/argo-cd/pull/6280 - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.valuesDirectoryURL - value: https://github.com/beekhof/patterns/raw/main - - name: global.pattern - value: common - syncPolicy: - automated: {} ---- -# Source: pattern-install/templates/argocd/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: "" -spec: - channel: gitops-1.13 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace From 63f7ca5bf1b319a00661ee1e04a9e9478b3ce3bd Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Mon, 16 Sep 2024 08:25:24 -0500 Subject: [PATCH 178/222] Remove ansible code in favor of external collection --- Makefile | 13 +- ansible/ansible.cfg | 6 - ansible/playbooks/acm/acmhub-get-ca.yaml | 53 - .../auto-approve-installplans.yaml | 40 - .../playbooks/hello-world/hello-world.yaml | 23 - ansible/playbooks/iib-ci/iib-ci.yaml | 8 - ansible/playbooks/iib-ci/lookup.yml | 46 - ansible/playbooks/k8s_secrets/k8s_secrets.yml | 9 - .../process_secrets/display_secrets_info.yml | 29 - .../process_secrets/process_secrets.yml | 50 - ansible/playbooks/vault/vault.yaml | 9 - .../write-token-kubeconfig.yml | 93 -- ansible/plugins/__init__.py | 0 ansible/plugins/filter/parse_acm_secrets.py | 84 -- .../module_utils/load_secrets_common.py | 124 --- .../plugins/module_utils/load_secrets_v1.py | 268 ----- .../plugins/module_utils/load_secrets_v2.py | 457 -------- .../plugins/module_utils/parse_secrets_v2.py | 528 ---------- ansible/plugins/modules/parse_secrets_info.py | 149 --- .../modules/vault_load_parsed_secrets.py | 303 ------ ansible/plugins/modules/vault_load_secrets.py | 209 ---- .../roles/cluster_pre_check/defaults/main.yml | 3 - .../roles/cluster_pre_check/tasks/main.yml | 26 - ansible/roles/find_vp_secrets/tasks/main.yml | 87 -- ansible/roles/iib_ci/README.md | 111 -- ansible/roles/iib_ci/defaults/main.yml | 13 - ansible/roles/iib_ci/handlers/main.yml | 2 - ansible/roles/iib_ci/meta/main.yml | 29 - .../iib_ci/tasks/fetch-operator-images.yml | 102 -- .../iib_ci/tasks/install-iib-in-cluster.yml | 56 - ansible/roles/iib_ci/tasks/main.yml | 76 -- .../iib_ci/tasks/mirror-related-images.yml | 217 ---- .../iib_ci/tasks/setup-internal-registry.yml | 108 -- .../iib_ci/templates/catalogSource.yaml.j2 | 9 - .../iib_ci/templates/htpasswd-oauth.yaml | 14 - .../imageContentSourcePolicy.yaml.j2 | 19 - .../templates/imageDigestMirror.yaml.j2 | 18 - ansible/roles/iib_ci/templates/mirror.map.j2 | 3 - ansible/roles/iib_ci/vars/main.yml | 2 - .../roles/k8s_secret_utils/defaults/main.yml | 2 - .../tasks/inject_k8s_secret.yml | 15 - .../tasks/inject_k8s_secrets.yml | 5 - ansible/roles/k8s_secret_utils/tasks/main.yml | 6 - .../k8s_secret_utils/tasks/parse_secrets.yml | 12 - ansible/roles/vault_utils/README.md | 241 ----- ansible/roles/vault_utils/defaults/main.yml | 26 - ansible/roles/vault_utils/handlers/main.yml | 2 - ansible/roles/vault_utils/meta/main.yml | 31 - ansible/roles/vault_utils/tasks/main.yml | 20 - .../tasks/push_parsed_secrets.yaml | 43 - .../roles/vault_utils/tasks/push_secrets.yaml | 125 --- .../roles/vault_utils/tasks/vault_init.yaml | 47 - .../vault_utils/tasks/vault_secrets_init.yaml | 118 --- .../vault_utils/tasks/vault_spokes_init.yaml | 228 ---- .../roles/vault_utils/tasks/vault_status.yaml | 61 -- .../roles/vault_utils/tasks/vault_unseal.yaml | 88 -- ansible/roles/vault_utils/tests/inventory | 2 - ansible/roles/vault_utils/tests/test.yml | 6 - .../vault_utils/values-secrets.v1.schema.json | 38 - .../vault_utils/values-secrets.v2.schema.json | 335 ------ ansible/roles/vault_utils/vars/main.yml | 2 - ansible/tests/unit/test_ini_file.py | 57 - ansible/tests/unit/test_parse_secrets.py | 983 ------------------ .../tests/unit/test_util_datastructures.py | 205 ---- .../unit/test_vault_load_parsed_secrets.py | 321 ------ ansible/tests/unit/test_vault_load_secrets.py | 389 ------- .../tests/unit/test_vault_load_secrets_v2.py | 761 -------------- ansible/tests/unit/v1/mcg-values-secret.yaml | 27 - .../tests/unit/v1/template-mcg-missing.yaml | 27 - .../tests/unit/v1/template-mcg-working.yaml | 26 - .../tests/unit/v1/values-secret-broken1.yaml | 6 - .../tests/unit/v1/values-secret-broken2.yaml | 6 - .../tests/unit/v1/values-secret-broken3.yaml | 9 - .../unit/v1/values-secret-empty-files.yaml | 15 - .../unit/v1/values-secret-empty-secrets.yaml | 16 - ansible/tests/unit/v1/values-secret-fqdn.yaml | 11 - ansible/tests/unit/v1/values-secret-good.yaml | 36 - ansible/tests/unit/v2/aws-example.ini | 4 - ansible/tests/unit/v2/test-file-contents | 1 - ansible/tests/unit/v2/test-file-contents.b64 | 1 - .../v2/values-secret-v2-base-k8s-backend.yaml | 9 - .../values-secret-v2-base-none-backend.yaml | 11 - ...values-secret-v2-base-unknown-backend.yaml | 9 - .../tests/unit/v2/values-secret-v2-base.yaml | 38 - .../v2/values-secret-v2-block-yamlstring.yaml | 16 - .../values-secret-v2-default-annotations.yaml | 13 - .../v2/values-secret-v2-default-labels.yaml | 11 - .../values-secret-v2-default-namespace.yaml | 8 - .../v2/values-secret-v2-defaultvp-policy.yaml | 25 - .../v2/values-secret-v2-emptyvaultprefix.yaml | 9 - .../values-secret-v2-file-contents-b64.yaml | 9 - ...es-secret-v2-file-contents-double-b64.yaml | 9 - .../v2/values-secret-v2-file-contents.yaml | 8 - .../v2/values-secret-v2-files-emptypath.yaml | 25 - ...-secret-v2-files-wrong-onmissingvalue.yaml | 26 - .../v2/values-secret-v2-files-wrongpath.yaml | 26 - .../v2/values-secret-v2-generate-base64.yaml | 21 - ...values-secret-v2-generic-onlygenerate.yaml | 33 - .../v2/values-secret-v2-ini-file-b64.yaml | 23 - .../unit/v2/values-secret-v2-ini-file.yaml | 21 - .../v2/values-secret-v2-more-namespaces.yaml | 11 - ...values-secret-v2-nondefault-namespace.yaml | 8 - ...es-secret-v2-none-no-targetnamespaces.yaml | 33 - ...es-secret-v2-nonexisting-backingstore.yaml | 23 - .../unit/v2/values-secret-v2-nopolicies.yaml | 24 - .../v2/values-secret-v2-novaultprefix.yaml | 8 - .../v2/values-secret-v2-onlygenerate.yaml | 33 - .../v2/values-secret-v2-override-labels.yaml | 13 - .../values-secret-v2-override-namespace.yaml | 10 - .../values-secret-v2-override-type-none.yaml | 14 - .../v2/values-secret-v2-override-type.yaml | 12 - .../v2/values-secret-v2-same-field-names.yaml | 14 - .../values-secret-v2-same-secret-names.yaml | 20 - .../v2/values-secret-v2-secret-base64.yaml | 11 - .../values-secret-v2-secret-binary-b64.yaml | 10 - .../v2/values-secret-v2-test-override.yaml | 28 - .../v2/values-secret-v2-wrong-ini-file.yaml | 9 - ...values-secret-v2-wrong-onmissingvalue.yaml | 20 - .../v2/values-secret-v2-wrong-override.yaml | 11 - .../values-secret-v2-wrong-vaultpolicy.yaml | 20 - requirements.yml | 4 + scripts/display-secrets-info.sh | 2 +- 122 files changed, 7 insertions(+), 8431 deletions(-) delete mode 100644 ansible/ansible.cfg delete mode 100644 ansible/playbooks/acm/acmhub-get-ca.yaml delete mode 100644 ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml delete mode 100644 ansible/playbooks/hello-world/hello-world.yaml delete mode 100644 ansible/playbooks/iib-ci/iib-ci.yaml delete mode 100644 ansible/playbooks/iib-ci/lookup.yml delete mode 100644 ansible/playbooks/k8s_secrets/k8s_secrets.yml delete mode 100644 ansible/playbooks/process_secrets/display_secrets_info.yml delete mode 100644 ansible/playbooks/process_secrets/process_secrets.yml delete mode 100644 ansible/playbooks/vault/vault.yaml delete mode 100644 ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml delete mode 100644 ansible/plugins/__init__.py delete mode 100644 ansible/plugins/filter/parse_acm_secrets.py delete mode 100644 ansible/plugins/module_utils/load_secrets_common.py delete mode 100644 ansible/plugins/module_utils/load_secrets_v1.py delete mode 100644 ansible/plugins/module_utils/load_secrets_v2.py delete mode 100644 ansible/plugins/module_utils/parse_secrets_v2.py delete mode 100644 ansible/plugins/modules/parse_secrets_info.py delete mode 100644 ansible/plugins/modules/vault_load_parsed_secrets.py delete mode 100644 ansible/plugins/modules/vault_load_secrets.py delete mode 100644 ansible/roles/cluster_pre_check/defaults/main.yml delete mode 100644 ansible/roles/cluster_pre_check/tasks/main.yml delete mode 100644 ansible/roles/find_vp_secrets/tasks/main.yml delete mode 100644 ansible/roles/iib_ci/README.md delete mode 100644 ansible/roles/iib_ci/defaults/main.yml delete mode 100644 ansible/roles/iib_ci/handlers/main.yml delete mode 100644 ansible/roles/iib_ci/meta/main.yml delete mode 100644 ansible/roles/iib_ci/tasks/fetch-operator-images.yml delete mode 100644 ansible/roles/iib_ci/tasks/install-iib-in-cluster.yml delete mode 100644 ansible/roles/iib_ci/tasks/main.yml delete mode 100644 ansible/roles/iib_ci/tasks/mirror-related-images.yml delete mode 100644 ansible/roles/iib_ci/tasks/setup-internal-registry.yml delete mode 100644 ansible/roles/iib_ci/templates/catalogSource.yaml.j2 delete mode 100644 ansible/roles/iib_ci/templates/htpasswd-oauth.yaml delete mode 100644 ansible/roles/iib_ci/templates/imageContentSourcePolicy.yaml.j2 delete mode 100644 ansible/roles/iib_ci/templates/imageDigestMirror.yaml.j2 delete mode 100644 ansible/roles/iib_ci/templates/mirror.map.j2 delete mode 100644 ansible/roles/iib_ci/vars/main.yml delete mode 100644 ansible/roles/k8s_secret_utils/defaults/main.yml delete mode 100644 ansible/roles/k8s_secret_utils/tasks/inject_k8s_secret.yml delete mode 100644 ansible/roles/k8s_secret_utils/tasks/inject_k8s_secrets.yml delete mode 100644 ansible/roles/k8s_secret_utils/tasks/main.yml delete mode 100644 ansible/roles/k8s_secret_utils/tasks/parse_secrets.yml delete mode 100644 ansible/roles/vault_utils/README.md delete mode 100644 ansible/roles/vault_utils/defaults/main.yml delete mode 100644 ansible/roles/vault_utils/handlers/main.yml delete mode 100644 ansible/roles/vault_utils/meta/main.yml delete mode 100644 ansible/roles/vault_utils/tasks/main.yml delete mode 100644 ansible/roles/vault_utils/tasks/push_parsed_secrets.yaml delete mode 100644 ansible/roles/vault_utils/tasks/push_secrets.yaml delete mode 100644 ansible/roles/vault_utils/tasks/vault_init.yaml delete mode 100644 ansible/roles/vault_utils/tasks/vault_secrets_init.yaml delete mode 100644 ansible/roles/vault_utils/tasks/vault_spokes_init.yaml delete mode 100644 ansible/roles/vault_utils/tasks/vault_status.yaml delete mode 100644 ansible/roles/vault_utils/tasks/vault_unseal.yaml delete mode 100644 ansible/roles/vault_utils/tests/inventory delete mode 100644 ansible/roles/vault_utils/tests/test.yml delete mode 100644 ansible/roles/vault_utils/values-secrets.v1.schema.json delete mode 100644 ansible/roles/vault_utils/values-secrets.v2.schema.json delete mode 100644 ansible/roles/vault_utils/vars/main.yml delete mode 100644 ansible/tests/unit/test_ini_file.py delete mode 100644 ansible/tests/unit/test_parse_secrets.py delete mode 100644 ansible/tests/unit/test_util_datastructures.py delete mode 100644 ansible/tests/unit/test_vault_load_parsed_secrets.py delete mode 100644 ansible/tests/unit/test_vault_load_secrets.py delete mode 100644 ansible/tests/unit/test_vault_load_secrets_v2.py delete mode 100644 ansible/tests/unit/v1/mcg-values-secret.yaml delete mode 100644 ansible/tests/unit/v1/template-mcg-missing.yaml delete mode 100644 ansible/tests/unit/v1/template-mcg-working.yaml delete mode 100644 ansible/tests/unit/v1/values-secret-broken1.yaml delete mode 100644 ansible/tests/unit/v1/values-secret-broken2.yaml delete mode 100644 ansible/tests/unit/v1/values-secret-broken3.yaml delete mode 100644 ansible/tests/unit/v1/values-secret-empty-files.yaml delete mode 100644 ansible/tests/unit/v1/values-secret-empty-secrets.yaml delete mode 100644 ansible/tests/unit/v1/values-secret-fqdn.yaml delete mode 100644 ansible/tests/unit/v1/values-secret-good.yaml delete mode 100644 ansible/tests/unit/v2/aws-example.ini delete mode 100644 ansible/tests/unit/v2/test-file-contents delete mode 100644 ansible/tests/unit/v2/test-file-contents.b64 delete mode 100644 ansible/tests/unit/v2/values-secret-v2-base-k8s-backend.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-base-none-backend.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-base-unknown-backend.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-base.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-block-yamlstring.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-default-annotations.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-default-labels.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-default-namespace.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-defaultvp-policy.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-emptyvaultprefix.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-file-contents-b64.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-file-contents-double-b64.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-file-contents.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-files-emptypath.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-files-wrong-onmissingvalue.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-files-wrongpath.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-generate-base64.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-generic-onlygenerate.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-ini-file-b64.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-ini-file.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-more-namespaces.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-nondefault-namespace.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-none-no-targetnamespaces.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-nonexisting-backingstore.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-nopolicies.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-novaultprefix.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-onlygenerate.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-override-labels.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-override-namespace.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-override-type-none.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-override-type.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-same-field-names.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-same-secret-names.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-secret-base64.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-secret-binary-b64.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-test-override.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-wrong-ini-file.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-wrong-onmissingvalue.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-wrong-override.yaml delete mode 100644 ansible/tests/unit/v2/values-secret-v2-wrong-vaultpolicy.yaml create mode 100644 requirements.yml diff --git a/Makefile b/Makefile index 3f2ba7a4..ce4a4a91 100644 --- a/Makefile +++ b/Makefile @@ -115,7 +115,7 @@ secrets-backend-none: ## Edits values files to remove secrets manager + ESO .PHONY: load-iib load-iib: ## CI target to install Index Image Bundles @set -e; if [ x$(INDEX_IMAGES) != x ]; then \ - ansible-playbook common/ansible/playbooks/iib-ci/iib-ci.yaml; \ + ansible-playbook rhvp.cluster_utils.iib-ci; \ else \ echo "No INDEX_IMAGES defined. Bailing out"; \ exit 1; \ @@ -218,7 +218,7 @@ TEST_OPTS= -f values-global.yaml \ --set global.clusterVersion="4.12" \ --set global.clusterPlatform=aws \ --set "clusterGroup.imperative.jobs[0].name"="test" \ - --set "clusterGroup.imperative.jobs[0].playbook"="ansible/test.yml" + --set "clusterGroup.imperative.jobs[0].playbook"="rhvp.cluster_utils.test" PATTERN_OPTS=-f common/examples/values-example.yaml EXECUTABLES=git helm oc ansible @@ -260,15 +260,6 @@ super-linter: ## Runs super linter locally -w /tmp/lint \ ghcr.io/super-linter/super-linter:slim-v7 -.PHONY: ansible-lint -ansible-lint: ## run ansible lint on ansible/ folder - podman run -it -v $(PWD):/workspace:rw,z --workdir /workspace --env ANSIBLE_CONFIG=./ansible/ansible.cfg \ - --entrypoint "/usr/local/bin/ansible-lint" quay.io/ansible/creator-ee:latest "-vvv" "ansible/" - -.PHONY: ansible-unittest -ansible-unittest: ## run ansible unit tests - pytest -r a --fulltrace --color yes ansible/tests/unit/test_*.py - .PHONY: deploy upgrade legacy-deploy legacy-upgrade deploy upgrade legacy-deploy legacy-upgrade: @echo "UNSUPPORTED TARGET: please switch to 'operator-deploy'"; exit 1 diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg deleted file mode 100644 index 652feb98..00000000 --- a/ansible/ansible.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[defaults] -localhost_warning=False -library=./plugins/modules:~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules -roles_path=./roles:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles -module_utils=~/.ansible/plugins/module_utils:./plugins/module_utils:/usr/share/ansible/plugins/module_utils -filter_plugins=~/.ansible/plugins/filter:./plugins/filter:/usr/share/ansible/plugins/filter diff --git a/ansible/playbooks/acm/acmhub-get-ca.yaml b/ansible/playbooks/acm/acmhub-get-ca.yaml deleted file mode 100644 index 770333ff..00000000 --- a/ansible/playbooks/acm/acmhub-get-ca.yaml +++ /dev/null @@ -1,53 +0,0 @@ -# This playbook fetches the hub cluster's CAbundle from ACM's objects -# and puts it in a secret inside the imperative namespace ---- -- name: ACM Get Hub CA - hosts: localhost - connection: local - gather_facts: false - become: false - vars: - ns: imperative - tasks: - - name: Find hub cluster - kubernetes.core.k8s_info: - kind: Secret - name: hub-kubeconfig-secret - namespace: open-cluster-management-agent - register: hub_cluster - - - name: Do nothing when no managed clusters are found - ansible.builtin.meta: end_play - when: hub_cluster['resources'][0]['data']['kubeconfig'] is not defined - - # FIXME(bandini) The assumption here is that there is a single hub cluster for each managed cluster - # - # oc extract secret/hub-kubeconfig-secret --keys=kubeconfig --to=- -n open-cluster-management-agent - # apiVersion: v1 - # clusters: - # - cluster: - # certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURNakNDQWhxZ0F3SU... - # server: https://api.bandini-dc.blueprints.rhecoeng.com:6443 - # name: default-cluster - - name: Get hub cluster facts - ansible.builtin.set_fact: - # kubeconfig is just a b64-econded yaml - hub_cluster_kubeconfig: "{{ hub_cluster['resources'][0]['data']['kubeconfig'] | b64decode | from_yaml }}" - - - name: Set CA fact - ansible.builtin.set_fact: - # The .get() call is needed because the key has dashes in it - hub_cluster_ca: "{{ hub_cluster_kubeconfig.clusters[0].cluster.get('certificate-authority-data') }}" - - - name: Create secret with managed cluster's CA - kubernetes.core.k8s: - state: present - definition: - kind: Secret - apiVersion: v1 - metadata: - name: "hub" - namespace: "{{ ns }}" - data: - caBundle: "{{ hub_cluster_ca }}" - type: Opaque diff --git a/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml b/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml deleted file mode 100644 index 6b6802d4..00000000 --- a/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# This playbook will watch for pending install plans of managed operators -# if they are in Manual and there's a startingCSV that must be installed ---- -- name: InstallPlan Auto-Approver - hosts: localhost - connection: local - gather_facts: false - become: false - - tasks: - - name: Get all installPlans from OpenShift - kubernetes.core.k8s_info: - api_version: operators.coreos.com/v1alpha1 - kind: InstallPlan - register: installplans - - - name: Get required CSVs from clusterGroup data - ansible.builtin.set_fact: - expected_csv: "{{ expected_csv | default([]) + [item.csv] }}" - when: item.csv | default(false) and - ((item.installPlanApproval | default("") == "Manual") or - (item.installPlanApproval | default("") == "" and global.options.installPlanApproval | default("") == "Manual")) - with_items: "{{ clusterGroup.subscriptions.values() }}" - - # TODO: loop over clusterGroup.subscriptions instead of installplans - # to allow certain control on the order of approvals - # IDEA: allow adding a per-installplan delay after the approval before - # moving forward to the next one - - name: Approve the missing installPlans - kubernetes.core.k8s_json_patch: - api_version: operators.coreos.com/v1alpha1 - kind: InstallPlan - name: "{{ item.metadata.name }}" - namespace: "{{ item.metadata.namespace }}" - patch: - - op: replace - path: /spec/approved - value: true - when: (item.spec.clusterServiceVersionNames | intersect(expected_csv | default([]))) | length > 0 - loop: "{{ installplans.resources }}" diff --git a/ansible/playbooks/hello-world/hello-world.yaml b/ansible/playbooks/hello-world/hello-world.yaml deleted file mode 100644 index c0a992a7..00000000 --- a/ansible/playbooks/hello-world/hello-world.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# This playbook is a simple hello-world playbook to show capabilities -# It creates a config-map inside the imperative namespace containing -# the helm variable "global.clusterDomain" ---- -- name: Hello World Example - hosts: localhost - connection: local - gather_facts: false - become: false - vars: - ns: imperative - tasks: - - name: Create secret with managed cluster's CA - kubernetes.core.k8s: - state: present - definition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: "hello-world" - namespace: "{{ ns }}" - data: - hello-cluster-domain: "{{ global['clusterDomain'] }}" diff --git a/ansible/playbooks/iib-ci/iib-ci.yaml b/ansible/playbooks/iib-ci/iib-ci.yaml deleted file mode 100644 index dc6e45cb..00000000 --- a/ansible/playbooks/iib-ci/iib-ci.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# This playbook invokes the iib_ci role ---- -- name: IIB CI playbook - hosts: localhost - connection: local - gather_facts: false - roles: - - iib_ci diff --git a/ansible/playbooks/iib-ci/lookup.yml b/ansible/playbooks/iib-ci/lookup.yml deleted file mode 100644 index f39b8ea3..00000000 --- a/ansible/playbooks/iib-ci/lookup.yml +++ /dev/null @@ -1,46 +0,0 @@ ---- -- name: IIB CI playbook - hosts: localhost - connection: local - gather_facts: false - vars: - rh_url: "https://datagrepper.engineering.redhat.com/raw?topic=/topic/VirtualTopic.eng.ci.redhat-container-image.index.built&delta=15780000&contains=%s" - operator: "openshift-gitops-1-gitops-operator-bundle" - ocp_versions: {} - tasks: - - name: Set url fact - ansible.builtin.set_fact: - url: "{{ rh_url | format(operator) }}" - - - name: Fetch URI - ansible.builtin.uri: - url: "{{ url }}" - return_content: true - register: jsoncontent - - - name: Setting content - ansible.builtin.set_fact: - content: "{{ jsoncontent['content'] | from_json }}" - - - name: Set messages fact - ansible.builtin.set_fact: - raw_messages: "{{ content.raw_messages }}" - - # The when clause is because if we already have an IIB for an ocp version we do not - # want to override it (combine will always override existing keys) - # Reason for this is that the messages are sorted last first and we only want the - # last entries - - name: Set output - ansible.builtin.set_fact: - ocp_versions: "{{ ocp_versions | combine({item['msg']['index']['ocp_version']: {'indeximage': item['msg']['index']['index_image'], 'bundleimage': item['msg']['index']['added_bundle_images'][0]}}) }}" - loop: "{{ raw_messages }}" - when: item['msg']['index']['ocp_version'] is not in ocp_versions - loop_control: - label: "{{ item['msg']['index']['ocp_version'] }}" - - - name: Print OCP versions for "{{ operator }}" - ansible.builtin.debug: - msg: "{{ item.key }} -> {{ item.value }}" - loop: "{{ ocp_versions | dict2items }}" - loop_control: - label: "{{ item.key }}" diff --git a/ansible/playbooks/k8s_secrets/k8s_secrets.yml b/ansible/playbooks/k8s_secrets/k8s_secrets.yml deleted file mode 100644 index 989a498a..00000000 --- a/ansible/playbooks/k8s_secrets/k8s_secrets.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: Secrets parsing and direct loading - hosts: localhost - connection: local - gather_facts: false - roles: - - find_vp_secrets - - cluster_pre_check - - k8s_secret_utils diff --git a/ansible/playbooks/process_secrets/display_secrets_info.yml b/ansible/playbooks/process_secrets/display_secrets_info.yml deleted file mode 100644 index 4d972359..00000000 --- a/ansible/playbooks/process_secrets/display_secrets_info.yml +++ /dev/null @@ -1,29 +0,0 @@ ---- -- name: Parse and display secrets - hosts: localhost - connection: local - gather_facts: false - vars: - secrets_backing_store: "vault" - tasks: - # Set the VALUES_SECRET environment variable to the file to parse - - name: Find and decrypt secrets if needed - ansible.builtin.include_role: - name: find_vp_secrets - - # find_vp_secrets will return a plaintext data structure called values_secrets_data - # This will allow us to determine schema version and which backend to use - - name: Determine how to load secrets - ansible.builtin.set_fact: - secrets_yaml: '{{ values_secrets_data | from_yaml }}' - - - name: Parse secrets data - no_log: '{{ override_no_log | default(true) }}' - parse_secrets_info: - values_secrets_plaintext: "{{ values_secrets_data }}" - secrets_backing_store: "{{ secrets_backing_store }}" - register: secrets_results - - - name: Display secrets data - ansible.builtin.debug: - var: secrets_results diff --git a/ansible/playbooks/process_secrets/process_secrets.yml b/ansible/playbooks/process_secrets/process_secrets.yml deleted file mode 100644 index ecc1b565..00000000 --- a/ansible/playbooks/process_secrets/process_secrets.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- -- name: Parse and load secrets - hosts: localhost - connection: local - gather_facts: false - vars: - secrets_role: 'vault_utils' - pattern_name: 'common' - pattern_dir: '.' - secrets_backing_store: 'vault' - tasks_from: 'push_parsed_secrets' - tasks: - - name: "Run secret-loading pre-requisites" - ansible.builtin.include_role: - name: '{{ item }}' - loop: - - cluster_pre_check - - find_vp_secrets - - # find_vp_secrets will return a plaintext data structure called values_secrets_data - # This will allow us to determine schema version and which backend to use - - name: Determine how to load secrets - ansible.builtin.set_fact: - secrets_yaml: '{{ values_secrets_data | from_yaml }}' - - - name: Parse secrets data - no_log: '{{ override_no_log | default(true) }}' - parse_secrets_info: - values_secrets_plaintext: "{{ values_secrets_data }}" - secrets_backing_store: "{{ secrets_backing_store }}" - register: secrets_results - - # Use the k8s secrets loader when explicitly requested - - name: Determine role to use to load secrets - ansible.builtin.set_fact: - secrets_role: 'k8s_secret_utils' - tasks_from: 'inject_k8s_secrets' - when: - - secrets_backing_store == "kubernetes" or secrets_backing_store == "none" - - secrets_yaml['version'] | default('2.0') >= '2.0' - - # secrets_role will have been changed from the default if needed - - name: Load secrets using designated role and tasks - ansible.builtin.include_role: - name: '{{ secrets_role }}' - tasks_from: '{{ tasks_from }}' - vars: - kubernetes_secret_objects: "{{ secrets_results['kubernetes_secret_objects'] }}" - vault_policies: "{{ secrets_results['vault_policies'] }}" - parsed_secrets: "{{ secrets_results['parsed_secrets'] }}" diff --git a/ansible/playbooks/vault/vault.yaml b/ansible/playbooks/vault/vault.yaml deleted file mode 100644 index b0da9405..00000000 --- a/ansible/playbooks/vault/vault.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: Vault initialization - hosts: localhost - connection: local - gather_facts: false - roles: - - find_vp_secrets - - cluster_pre_check - - vault_utils diff --git a/ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml b/ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml deleted file mode 100644 index dcb23111..00000000 --- a/ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml +++ /dev/null @@ -1,93 +0,0 @@ ---- -- name: Test k8s authentication methods - hosts: localhost - connection: local - gather_facts: false - become: false - vars: - kubeconfig_file: '~/.kube/config' - k8s_host: '{{ lookup("env", "K8S_AUTH_HOST") }}' - k8s_validate_certs: '{{ lookup("env", "K8S_AUTH_VERIFY_SSL") | default(false) | bool }}' - k8s_username: '{{ lookup("env", "K8S_AUTH_USERNAME") | default("kubeconfig") }}' - k8s_password: '{{ lookup("env", "K8S_AUTH_PASSWORD") | default(omit) }}' - k8s_api_key: '{{ lookup("env", "K8S_AUTH_TOKEN") | default(omit) }}' - k8s_ca_cert_file: '{{ lookup("env", "K8S_AUTH_SSL_CA_CERT") | default(omit) }}' - tasks: - - name: Check for pre-existing kubeconfig - ansible.builtin.stat: - path: '{{ kubeconfig_file }}' - register: kubeconfig_stat - - - name: Exit if kubeconfig found - ansible.builtin.fail: - msg: '{{ kubeconfig_file }} already exists! Exiting' - when: kubeconfig_stat.stat.exists - - - name: Get namespaces to test parameters - kubernetes.core.k8s_info: - host: '{{ k8s_host }}' - validate_certs: '{{ k8s_validate_certs }}' - username: '{{ k8s_username }}' - api_key: '{{ k8s_api_key }}' - ca_cert: '{{ k8s_ca_cert_file | default(omit) }}' - kind: namespace - when: k8s_api_key - - - name: Login explicitly - when: not k8s_api_key - block: - - name: Login explicitly to get token - kubernetes.core.k8s_auth: - host: '{{ k8s_host }}' - validate_certs: '{{ k8s_validate_certs }}' - username: '{{ k8s_username }}' - password: '{{ k8s_password }}' - ca_cert: '{{ k8s_ca_cert_file | default(omit) }}' - register: auth - - - name: Set api_key - ansible.builtin.set_fact: - k8s_api_key: '{{ auth.openshift_auth.api_key }}' - - - name: Update username if needed - ansible.builtin.set_fact: - config_k8s_username: 'kube:admin' - when: k8s_username == 'kubeadmin' - - - name: Determine clustername - ansible.builtin.set_fact: - config_k8s_clustername: "{{ k8s_host | regex_replace('https://', '') | regex_replace('\\.', '-') }}" - - - name: Write config file - ansible.builtin.copy: - content: |- - apiVersion: v1 - clusters: - - cluster: - {% if k8s_validate_certs is false %} - insecure-skip-tls-verify: true - {% endif %} - {% if k8s_ca_cert_file -%} - certificate-authority-data: {{ lookup("file", k8s_ca_cert_file) | b64encode }} - {% endif %} - server: {{ k8s_host }} - name: {{ config_k8s_clustername }} - contexts: - - context: - cluster: {{ config_k8s_clustername }} - namespace: default - user: {{ config_k8s_username | default(k8s_username) }}/{{ config_k8s_clustername }} - name: default/{{ config_k8s_clustername }}/{{ config_k8s_username | default(k8s_username) }} - current-context: default/{{ config_k8s_clustername }}/{{ config_k8s_username | default(k8s_username) }} - kind: Config - preferences: {} - users: - - name: {{ config_k8s_username | default(k8s_username) }}/{{ config_k8s_clustername }} - user: - token: {{ k8s_api_key }} - dest: '{{ kubeconfig_file }}' - mode: '0640' - - - name: Notify user - ansible.builtin.debug: - msg: "Wrote {{ kubeconfig_file }}" diff --git a/ansible/plugins/__init__.py b/ansible/plugins/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/ansible/plugins/filter/parse_acm_secrets.py b/ansible/plugins/filter/parse_acm_secrets.py deleted file mode 100644 index 1c5148e3..00000000 --- a/ansible/plugins/filter/parse_acm_secrets.py +++ /dev/null @@ -1,84 +0,0 @@ -# This filter takes a bunch of acm secrets that represent the remote clusters -# (Usually it is all secrets that are labeled with: -# "apps.open-cluster-management.io/secret-type=acm-cluster") - -# These secrets are usually in the form of: -# data: -# config: ewogIC... -# name: bWNnLW9uZQ== -# server: aHR0cHM6Ly9hcGkubWNnLW9uZS5ibHVlcHJpbnRzLnJoZWNvZW5nLmNvbTo2NDQz - -# The filter parses the secret (name, server, config) and returns a dictionary of secrets in the -# following form: -# : -# name: -# cluster_fqdn: -# server_api: https://api.:6443 -# bearerToken: -# tlsClientConfig: -# vault_path: "hub" when it is the ACM hub or in the other cases - -import json -from base64 import b64decode - - -# These are the labels of an acm secret -# labels: -# apps.open-cluster-management.io/cluster-name: local-cluster -# apps.open-cluster-management.io/cluster-server: api.mcg-hub.blueprints.rhecoeng.com -# apps.open-cluster-management.io/secret-type: acm-cluster -def get_cluster_name(secret): - if "metadata" in secret and "labels" in secret["metadata"]: - return secret["metadata"]["labels"].get( - "apps.open-cluster-management.io/cluster-name", None - ) - return None - - -def is_cluster_a_hub(name): - if name == "local-cluster": - return True - return False - - -def get_cluster_fqdn(secret): - if "metadata" in secret and "labels" in secret["metadata"]: - server = secret["metadata"]["labels"].get( - "apps.open-cluster-management.io/cluster-server", None - ) - # It is rather hard to override this in an OCP deployment so we are - # okay in just dropping 'api.' - return server.removeprefix("api.") - return None - - -def parse_acm_secrets(secrets): - ret = {} - for secret in secrets: - cluster = get_cluster_name(secret) - if cluster is None: - continue - - ret[cluster] = {} - name = b64decode(secret["data"]["name"]) - ret[cluster]["name"] = name - ret[cluster]["server_api"] = b64decode(secret["data"]["server"]) - fqdn = get_cluster_fqdn(secret) - ret[cluster]["cluster_fqdn"] = fqdn - if is_cluster_a_hub(name): - ret[cluster]["vault_path"] = "hub" - else: - ret[cluster]["vault_path"] = fqdn - - config = b64decode(secret["data"]["config"]) - parsed_config = json.loads(config) - ret[cluster]["bearerToken"] = parsed_config["bearerToken"] - ret[cluster]["tlsClientConfig"] = parsed_config["tlsClientConfig"] - - return ret - - -class FilterModule: - - def filters(self): - return {"parse_acm_secrets": parse_acm_secrets} diff --git a/ansible/plugins/module_utils/load_secrets_common.py b/ansible/plugins/module_utils/load_secrets_common.py deleted file mode 100644 index b4ebc816..00000000 --- a/ansible/plugins/module_utils/load_secrets_common.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Module that implements some common functions -""" - -import configparser -from collections.abc import MutableMapping - - -def find_dupes(array): - """ - Returns duplicate items in a list - - Parameters: - l(list): Array to check for duplicate entries - - Returns: - dupes(list): Array containing all the duplicates and [] is there are none - """ - seen = set() - dupes = [] - for x in array: - if x in seen: - dupes.append(x) - else: - seen.add(x) - return dupes - - -def get_version(syaml): - """ - Return the version: of the parsed yaml object. If it does not exist - return 1.0 - - Returns: - ret(str): The version value in of the top-level 'version:' key - """ - return str(syaml.get("version", "1.0")) - - -def flatten(dictionary, parent_key=False, separator="."): - """ - Turn a nested dictionary into a flattened dictionary and also - drop any key that has 'None' as their value - - Parameters: - dictionary(dict): The dictionary to flatten - - parent_key(str): The string to prepend to dictionary's keys - - separator(str): The string used to separate flattened keys - - Returns: - - dictionary: A flattened dictionary where the keys represent the - path to reach the leaves - """ - - items = [] - for key, value in dictionary.items(): - new_key = str(parent_key) + separator + key if parent_key else key - if isinstance(value, MutableMapping): - items.extend(flatten(value, new_key, separator).items()) - elif isinstance(value, list): - for k, v in enumerate(value): - items.extend(flatten({str(k): v}, new_key).items()) - else: - if value is not None: - items.append((new_key, value)) - return dict(items) - - -def get_ini_value(inifile, inisection, inikey): - """ - Return a value from an ini-file or 'None' if it does not exist - - Parameters: - inifile(str): The path to the ini-file - - inisection(str): The section in the ini-file to look for the key - - inikey(str): The key to look up inside the ini-file's section - - Returns: - - obj: The value of the key or None if it does not exist - """ - config = configparser.ConfigParser() - config.read(inifile) - return config.get(inisection, inikey, fallback=None) - - -def stringify_dict(input_dict): - """ - Return a dict whose keys and values are all co-erced to strings, for creating labels and annotations in the - python Kubernetes module - - Parameters: - input_dict(dict): A dictionary of keys and values - - Returns: - - obj: The same dict in the same order but with the keys coerced to str - """ - output_dict = {} - - for key, value in input_dict.items(): - output_dict[str(key)] = str(value) - - return output_dict diff --git a/ansible/plugins/module_utils/load_secrets_v1.py b/ansible/plugins/module_utils/load_secrets_v1.py deleted file mode 100644 index 8b89d85a..00000000 --- a/ansible/plugins/module_utils/load_secrets_v1.py +++ /dev/null @@ -1,268 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Module that implements V1 of the values-secret.yaml spec -""" - -import base64 -import os -import time - -import yaml -from ansible.module_utils.load_secrets_common import flatten, get_version - - -class LoadSecretsV1: - - def __init__( - self, - module, - syaml, - basepath, - namespace, - pod, - values_secret_template, - check_missing_secrets, - ): - self.module = module - self.basepath = basepath - self.namespace = namespace - self.pod = pod - self.values_secret_template = values_secret_template - self.check_missing_secrets = check_missing_secrets - self.syaml = syaml - - def _run_command(self, command, attempts=1, sleep=3): - """ - Runs a command on the host ansible is running on. A failing command - will raise an exception in this function directly (due to check=True) - - Parameters: - command(str): The command to be run. - attempts(int): Number of times to retry in case of Error (defaults to 1) - sleep(int): Number of seconds to wait in between retry attempts (defaults to 3s) - - Returns: - ret(subprocess.CompletedProcess): The return value from run() - """ - for attempt in range(attempts): - ret = self.module.run_command( - command, - check_rc=True, - use_unsafe_shell=True, - environ_update=os.environ.copy(), - ) - if ret[0] == 0: - return ret - if attempt >= attempts - 1: - return ret - time.sleep(sleep) - - def sanitize_values(self): - """ - Sanitizes the secrets YAML object. If a specific secret key has - s3.accessKey and s3.secretKey but not s3Secret, the latter will be - generated as the base64 encoding of both s3.accessKey and s3.secretKey. - - secrets: - test: - s3.accessKey: "1234" - s3.secretKey: "4321" - - will push three secrets at 'secret/hub/test': - - s3.accessKey: 1234 - s3.secretKey: 4321 - s3Secret: czMuYWNjZXNzS2V5OiAxMjM0CnMzLnNlY3JldEtleTogNDMyMQ== - - Parameters: - - Returns: - Nothing: Updates self.syaml(obj) - """ - v = get_version(self.syaml) - if v != "1.0": - self.module.fail_json(f"Version is not 1.0: {v}") - - if not ("secrets" in self.syaml or "files" in self.syaml): - self.module.fail_json( - f"Values secrets file does not contain 'secrets' or" - f"'files' keys: {self.syaml}" - ) - - if self.check_missing_secrets and self.values_secret_template == "": - self.module.fail_json( - "No values_secret_template defined and check_missing_secrets set to True" - ) - # If the user specified check_for_missing_secrets then we read values_secret_template - # and check if there are any missing secrets. Makes sense only for v1.0 - if self.check_missing_secrets: - self.check_for_missing_secrets() - - secrets = self.syaml.get("secrets", {}) - # We need to explicitely check for None because the file might contain the - # top-level 'secrets:' or 'files:' key but have nothing else under it which will - # return None and not {} - if secrets is None: - secrets = {} - files = self.syaml.get("files", {}) - if files is None: - files = {} - if len(secrets) == 0 and len(files) == 0: - self.module.fail_json( - "Neither 'secrets' nor 'files have any secrets to be parsed" - ) - - if isinstance(secrets, list) or isinstance(files, list): - self.module.fail_json("Neither 'secrets' nor 'files can be lists") - - for secret in secrets: - if not isinstance(secrets[secret], dict): - self.module.fail_json( - "Each key under 'secrets' needs to point to " - "a dictionary of key value pairs" - ) - - for file in files: - path = files[file] - if not os.path.isfile(os.path.expanduser(path)): - self.module.fail_json(f"File {path} does not exist") - - # If s3Secret key does not exist but s3.accessKey and s3.secretKey do exist - # generate s3Secret so a user does not need to do it manually which tends to be error-prone - for secret in secrets: - tmp = secrets[secret] - if ( - "s3.accessKey" in tmp - and "s3.secretKey" in tmp - and "s3Secret" not in tmp - ): - s3secret = ( - f"s3.accessKey: {tmp['s3.accessKey']}\n" - f"s3.secretKey: {tmp['s3.secretKey']}" - ) - s3secretb64 = base64.b64encode(s3secret.encode()) - secrets[secret]["s3Secret"] = s3secretb64.decode("utf-8") - - def get_secrets_vault_paths(self, keyname): - """ - Walks a secrets yaml object to look for all top-level keys that start with - 'keyname' and returns a list of tuples [(keyname1, path1), (keyname2, path2)...] - where the path is the relative vault path - For example, given a yaml with the following: - secrets: - foo: bar - secrets.region1: - foo: baz - secrets.region2: - foo: barbaz - - a call with keyname set to 'secrets' will return the following: - [('secrets', 'hub'), ('secrets', 'region1'), ('secrets', 'region2')] - - Parameters: - keyname(str): The keytypes to look for either usually 'secrets' or 'files' - - Returns: - keys_paths(list): List of tuples containing (keyname, relative-vault-path) - """ - all_keys = self.syaml.keys() - keys_paths = [] - for key in all_keys: - # We skip any key that does not start with 'secrets' or 'files' - # (We should probably bail out in the presence of unexpected top-level keys) - if not key.startswith(keyname): - continue - - # If there is no '.' after secrets or files, assume the secrets need to - # go to the hub vault path - if key == keyname: - keys_paths.append((key, "hub")) - continue - - # We are in the presence of either 'secrets.region-one' or 'files.cluster1' top-level keys - tmp = key.split(".", 1) - if len(tmp) != 2: - self.module.fail_json( - f"values-secrets.yaml key is non-conformant: {key}" - ) - - keys_paths.append((key, tmp[1])) - - return keys_paths - - # NOTE(bandini): we shell out to oc exec it because of - # https://github.com/ansible-collections/kubernetes.core/issues/506 and - # https://github.com/kubernetes/kubernetes/issues/89899. Until those are solved - # it makes little sense to invoke the APIs via the python wrappers - def inject_secrets(self): - """ - Walks a secrets yaml object and injects all the secrets into the vault via 'oc exec' calls - - Parameters: - - Returns: - counter(int): The number of secrets injected - """ - counter = 0 - for i in self.get_secrets_vault_paths("secrets"): - path = f"{self.basepath}/{i[1]}" - for secret in self.syaml[i[0]] or []: - properties = "" - for key, value in self.syaml[i[0]][secret].items(): - properties += f"{key}='{value}' " - properties = properties.rstrip() - cmd = ( - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"\"vault kv put '{path}/{secret}' {properties}\"" - ) - self._run_command(cmd, attempts=3) - counter += 1 - - for i in self.get_secrets_vault_paths("files"): - path = f"{self.basepath}/{i[1]}" - for filekey in self.syaml[i[0]] or []: - file = os.path.expanduser(self.syaml[i[0]][filekey]) - cmd = ( - f"cat '{file}' | oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"'cat - > /tmp/vcontent'; " - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c 'base64 --wrap=0 /tmp/vcontent | " - f"vault kv put {path}/{filekey} b64content=- content=@/tmp/vcontent; " - f"rm /tmp/vcontent'" - ) - self._run_command(cmd, attempts=3) - counter += 1 - return counter - - def check_for_missing_secrets(self): - with open(self.values_secret_template, "r", encoding="utf-8") as file: - template_yaml = yaml.safe_load(file.read()) - if template_yaml is None: - self.module.fail_json(f"Template {self.values_secret_template} is empty") - - syaml_flat = flatten(self.syaml) - template_flat = flatten(template_yaml) - - syaml_keys = set(syaml_flat.keys()) - template_keys = set(template_flat.keys()) - - if template_keys <= syaml_keys: - return - - diff = template_keys - syaml_keys - self.module.fail_json( - f"Values secret yaml is missing needed secrets from the templates: {diff}" - ) diff --git a/ansible/plugins/module_utils/load_secrets_v2.py b/ansible/plugins/module_utils/load_secrets_v2.py deleted file mode 100644 index 46cdcffa..00000000 --- a/ansible/plugins/module_utils/load_secrets_v2.py +++ /dev/null @@ -1,457 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Module that implements V2 of the values-secret.yaml spec -""" - -import base64 -import getpass -import os -import time - -from ansible.module_utils.load_secrets_common import ( - find_dupes, - get_ini_value, - get_version, -) - -default_vp_vault_policies = { - "validatedPatternDefaultPolicy": ( - "length=20\n" - 'rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\n' - 'rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\n' - 'rule "charset" { charset = "0123456789" min-chars = 1 }\n' - 'rule "charset" { charset = "!@#%^&*" min-chars = 1 }\n' - ) -} - - -class LoadSecretsV2: - - def __init__(self, module, syaml, namespace, pod): - self.module = module - self.namespace = namespace - self.pod = pod - self.syaml = syaml - - def _run_command(self, command, attempts=1, sleep=3, checkrc=True): - """ - Runs a command on the host ansible is running on. A failing command - will raise an exception in this function directly (due to check=True) - - Parameters: - command(str): The command to be run. - attempts(int): Number of times to retry in case of Error (defaults to 1) - sleep(int): Number of seconds to wait in between retry attempts (defaults to 3s) - - Returns: - ret(subprocess.CompletedProcess): The return value from run() - """ - for attempt in range(attempts): - ret = self.module.run_command( - command, - check_rc=checkrc, - use_unsafe_shell=True, - environ_update=os.environ.copy(), - ) - if ret[0] == 0: - return ret - if attempt >= attempts - 1: - return ret - time.sleep(sleep) - - def _get_backingstore(self): - """ - Return the backingStore: of the parsed yaml object. If it does not exist - return 'vault' - - Returns: - ret(str): The value of the top-level 'backingStore:' key - """ - return str(self.syaml.get("backingStore", "vault")) - - def _get_vault_policies(self, enable_default_vp_policies=True): - # We start off with the hard-coded default VP policy and add the user-defined ones - if enable_default_vp_policies: - policies = default_vp_vault_policies.copy() - else: - policies = {} - policies.update(self.syaml.get("vaultPolicies", {})) - return policies - - def _get_secrets(self): - return self.syaml.get("secrets", {}) - - def _get_field_on_missing_value(self, f): - # By default if 'onMissingValue' is missing we assume we need to - # error out whenever the value is missing - return f.get("onMissingValue", "error") - - def _get_field_value(self, f): - return f.get("value", None) - - def _get_field_path(self, f): - return f.get("path", None) - - def _get_field_ini_file(self, f): - return f.get("ini_file", None) - - def _get_field_kind(self, f): - # value: null will be interpreted with None, so let's just - # check for the existence of the field, as we use 'value: null' to say - # "we want a value/secret and not a file path" - found = [] - for i in ["value", "path", "ini_file"]: - if i in f: - found.append(i) - - if len(found) > 1: # you can only have one of value, path and ini_file - self.module.fail_json(f"Both '{found[0]}' and '{found[1]}' cannot be used") - - if len(found) == 0: - return "" - return found[0] - - def _get_field_prompt(self, f): - return f.get("prompt", None) - - def _get_field_base64(self, f): - return bool(f.get("base64", False)) - - def _get_field_override(self, f): - return bool(f.get("override", False)) - - # This function could use some rewriting and it should call a specific validation function - # for each type (value, path, ini_file) - def _validate_field(self, f): - # These fields are mandatory - try: - _ = f["name"] - except KeyError: - return (False, f"Field {f} is missing name") - - on_missing_value = self._get_field_on_missing_value(f) - if on_missing_value not in ["error", "generate", "prompt"]: - return (False, f"onMissingValue: {on_missing_value} is invalid") - - value = self._get_field_value(f) - path = self._get_field_path(f) - ini_file = self._get_field_ini_file(f) - kind = self._get_field_kind(f) - if kind == "ini_file": - # if we are using ini_file then at least ini_key needs to be defined - # ini_section defaults to 'default' when omitted - ini_key = f.get("ini_key", None) - if ini_key is None: - return ( - False, - "ini_file requires at least ini_key to be defined", - ) - - # Test if base64 is a correct boolean (defaults to False) - _ = self._get_field_base64(f) - _ = self._get_field_override(f) - - vault_policy = f.get("vaultPolicy", None) - if vault_policy is not None and vault_policy not in self._get_vault_policies(): - return ( - False, - f"Secret has vaultPolicy set to {vault_policy} but no such policy exists", - ) - - if on_missing_value in ["error"]: - if ( - (value is None or len(value) < 1) - and (path is None or len(path) < 1) - and (ini_file is None or len(ini_file) < 1) - ): - return ( - False, - "Secret has onMissingValue set to 'error' and has neither value nor path nor ini_file set", - ) - if path is not None and not os.path.isfile(os.path.expanduser(path)): - return (False, f"Field has non-existing path: {path}") - - if ini_file is not None and not os.path.isfile( - os.path.expanduser(ini_file) - ): - return (False, f"Field has non-existing ini_file: {ini_file}") - - if "override" in f: - return ( - False, - "'override' attribute requires 'onMissingValue' to be set to 'generate'", - ) - - if on_missing_value in ["generate"]: - if value is not None: - return ( - False, - "Secret has onMissingValue set to 'generate' but has a value set", - ) - if path is not None: - return ( - False, - "Secret has onMissingValue set to 'generate' but has a path set", - ) - if vault_policy is None: - return ( - False, - "Secret has no vaultPolicy but onMissingValue is set to 'generate'", - ) - - if on_missing_value in ["prompt"]: - # When we prompt, the user needs to set one of the following: - # - value: null # prompt for a secret without a default value - # - value: 123 # prompt for a secret but use a default value - # - path: null # prompt for a file path without a default value - # - path: /tmp/ca.crt # prompt for a file path with a default value - if "value" not in f and "path" not in f: - return ( - False, - "Secret has onMissingValue set to 'prompt' but has no value nor path fields", - ) - - if "override" in f: - return ( - False, - "'override' attribute requires 'onMissingValue' to be set to 'generate'", - ) - - return (True, "") - - def _validate_secrets(self): - secrets = self._get_secrets() - if len(secrets) == 0: - self.module.fail_json("No secrets found") - - names = [] - for s in secrets: - # These fields are mandatory - for i in ["name"]: - try: - _ = s[i] - except KeyError: - return (False, f"Secret {s['name']} is missing {i}") - names.append(s["name"]) - - vault_prefixes = s.get("vaultPrefixes", ["hub"]) - # This checks for the case when vaultPrefixes: is specified but empty - if vault_prefixes is None or len(vault_prefixes) == 0: - return (False, f"Secret {s['name']} has empty vaultPrefixes") - - fields = s.get("fields", []) - if len(fields) == 0: - return (False, f"Secret {s['name']} does not have any fields") - - field_names = [] - for i in fields: - (ret, msg) = self._validate_field(i) - if not ret: - return (False, msg) - field_names.append(i["name"]) - field_dupes = find_dupes(field_names) - if len(field_dupes) > 0: - return (False, f"You cannot have duplicate field names: {field_dupes}") - - dupes = find_dupes(names) - if len(dupes) > 0: - return (False, f"You cannot have duplicate secret names: {dupes}") - return (True, "") - - def inject_vault_policies(self): - for name, policy in self._get_vault_policies().items(): - cmd = ( - f"echo '{policy}' | oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"'cat - > /tmp/{name}.hcl';" - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c 'vault write sys/policies/password/{name} " - f" policy=@/tmp/{name}.hcl'" - ) - self._run_command(cmd, attempts=3) - - def sanitize_values(self): - """ - Sanitizes the secrets YAML object version 2.0 - - Parameters: - - Returns: - Nothing: Updates self.syaml(obj) if needed - """ - v = get_version(self.syaml) - if v != "2.0": - self.module.fail_json(f"Version is not 2.0: {v}") - - backing_store = self._get_backingstore() - if backing_store != "vault": # we currently only support vault - self.module.fail_json( - f"Currently only the 'vault' backingStore is supported: {backing_store}" - ) - - (ret, msg) = self._validate_secrets() - if not ret: - self.module.fail_json(msg) - - def _get_secret_value(self, name, field): - on_missing_value = self._get_field_on_missing_value(field) - # We cannot use match + case as RHEL8 has python 3.9 (it needs 3.10) - # We checked for errors in _validate_secrets() already - if on_missing_value == "error": - return field.get("value") - elif on_missing_value == "prompt": - prompt = self._get_field_prompt(field) - if prompt is None: - prompt = f"Type secret for {name}/{field['name']}: " - value = self._get_field_value(field) - if value is not None: - prompt += f" [{value}]" - prompt += ": " - return getpass.getpass(prompt) - return None - - def _get_file_path(self, name, field): - on_missing_value = self._get_field_on_missing_value(field) - if on_missing_value == "error": - return os.path.expanduser(field.get("path")) - elif on_missing_value == "prompt": - prompt = self._get_field_prompt(field) - path = self._get_field_path(field) - if path is None: - path = "" - - if prompt is None: - text = f"Type path for file {name}/{field['name']} [{path}]: " - else: - text = f"{prompt} [{path}]: " - - newpath = getpass.getpass(text) - if newpath == "": # Set the default if no string was entered - newpath = path - - if os.path.isfile(os.path.expanduser(newpath)): - return newpath - self.module.fail_json(f"File {newpath} not found, exiting") - - self.module.fail_json("File with wrong onMissingValue") - - def _vault_secret_attr_exists(self, mount, prefix, secret_name, attribute): - cmd = ( - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f'"vault kv get -mount={mount} -field={attribute} {prefix}/{secret_name}"' - ) - # we ignore stdout and stderr - (ret, _, _) = self._run_command(cmd, attempts=1, checkrc=False) - if ret == 0: - return True - - return False - - def _inject_field(self, secret_name, f, mount, prefixes, first=False): - on_missing_value = self._get_field_on_missing_value(f) - override = self._get_field_override(f) - kind = self._get_field_kind(f) - # If we're generating the password then we just push the secret in the vault directly - verb = "put" if first else "patch" - b64 = self._get_field_base64(f) - if kind in ["value", ""]: - if on_missing_value == "generate": - if kind == "path": - self.module.fail_json( - "You cannot have onMissingValue set to 'generate' with a path" - ) - vault_policy = f.get("vaultPolicy") - gen_cmd = f"vault read -field=password sys/policies/password/{vault_policy}/generate" - if b64: - gen_cmd += " | base64 --wrap=0" - for prefix in prefixes: - # if the override field is False and the secret attribute exists at the prefix then we just - # skip, as we do not want to overwrite the existing secret - if not override and self._vault_secret_attr_exists( - mount, prefix, secret_name, f["name"] - ): - continue - cmd = ( - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"\"{gen_cmd} | vault kv {verb} -mount={mount} {prefix}/{secret_name} {f['name']}=-\"" - ) - self._run_command(cmd, attempts=3) - return - - # If we're not generating the secret inside the vault directly we either read it from the file ("error") - # or we are prompting the user for it - secret = self._get_secret_value(secret_name, f) - if b64: - secret = base64.b64encode(secret.encode()).decode("utf-8") - for prefix in prefixes: - cmd = ( - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"\"vault kv {verb} -mount={mount} {prefix}/{secret_name} {f['name']}='{secret}'\"" - ) - self._run_command(cmd, attempts=3) - - elif kind == "path": # path. we upload files - # If we're generating the password then we just push the secret in the vault directly - verb = "put" if first else "patch" - path = self._get_file_path(secret_name, f) - for prefix in prefixes: - if b64: - b64_cmd = "| base64 --wrap=0 " - else: - b64_cmd = "" - cmd = ( - f"cat '{path}' | oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"'cat - {b64_cmd}> /tmp/vcontent'; " - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c '" - f"vault kv {verb} -mount={mount} {prefix}/{secret_name} {f['name']}=@/tmp/vcontent; " - f"rm /tmp/vcontent'" - ) - self._run_command(cmd, attempts=3) - elif kind == "ini_file": # ini_file. we parse an ini_file - verb = "put" if first else "patch" - ini_file = os.path.expanduser(f.get("ini_file")) - ini_section = f.get("ini_section", "default") - ini_key = f.get("ini_key") - secret = get_ini_value(ini_file, ini_section, ini_key) - if b64: - secret = base64.b64encode(secret.encode()).decode("utf-8") - for prefix in prefixes: - cmd = ( - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"\"vault kv {verb} -mount={mount} {prefix}/{secret_name} {f['name']}='{secret}'\"" - ) - self._run_command(cmd, attempts=3) - - # This assumes that self.sanitize_values() has already been called - # so we do a lot less validation as it has already happened - def inject_secrets(self): - # This must come first as some passwords might depend on vault policies to exist. - # It is a noop when no policies are defined - self.inject_vault_policies() - secrets = self._get_secrets() - - total_secrets = 0 # Counter for all the secrets uploaded - for s in secrets: - counter = 0 # This counter is to use kv put on first secret and kv patch on latter - sname = s.get("name") - fields = s.get("fields", []) - mount = s.get("vaultMount", "secret") - vault_prefixes = s.get("vaultPrefixes", ["hub"]) - for i in fields: - self._inject_field(sname, i, mount, vault_prefixes, counter == 0) - counter += 1 - total_secrets += 1 - - return total_secrets diff --git a/ansible/plugins/module_utils/parse_secrets_v2.py b/ansible/plugins/module_utils/parse_secrets_v2.py deleted file mode 100644 index f88579b6..00000000 --- a/ansible/plugins/module_utils/parse_secrets_v2.py +++ /dev/null @@ -1,528 +0,0 @@ -# Copyright 2022, 2023 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Module that implements V2 of the values-secret.yaml spec -""" - -import base64 -import getpass -import os - -from ansible.module_utils.load_secrets_common import ( - find_dupes, - get_ini_value, - get_version, - stringify_dict, -) - -default_vp_vault_policies = { - "validatedPatternDefaultPolicy": ( - "length=20\n" - 'rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\n' - 'rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\n' - 'rule "charset" { charset = "0123456789" min-chars = 1 }\n' - 'rule "charset" { charset = "!@#%^&*" min-chars = 1 }\n' - ) -} - -secret_store_namespace = "validated-patterns-secrets" - - -class ParseSecretsV2: - - def __init__(self, module, syaml, secrets_backing_store): - self.module = module - self.syaml = syaml - self.secrets_backing_store = str(secrets_backing_store) - self.secret_store_namespace = None - self.parsed_secrets = {} - self.kubernetes_secret_objects = [] - self.vault_policies = {} - - def _get_backingstore(self): - """ - Backing store is now influenced by the caller more than the file. Setting - Return the backingStore: of the parsed yaml object. In most cases the file - key was not set anyway - since vault was the only supported option. Since - we are introducing new options now, this method of defining behavior is - deprecated, but if the file key is included it must match the option defined - by values-global in the pattern, or there is an error. The default remains - 'vault' if the key is unspecified. - - Returns: - ret(str): The value of the top-level 'backingStore:' key - """ - file_backing_store = str(self.syaml.get("backingStore", "unset")) - - if file_backing_store == "unset": - pass - else: - if file_backing_store != self.secrets_backing_store: - self.module.fail_json( - f"Secrets file specifies '{file_backing_store}' backend but pattern config " - f"specifies '{self.secrets_backing_store}'." - ) - - return self.secrets_backing_store - - def _get_vault_policies(self, enable_default_vp_policies=True): - # We start off with the hard-coded default VP policy and add the user-defined ones - if enable_default_vp_policies: - policies = default_vp_vault_policies.copy() - else: - policies = {} - - # This is useful for embedded newlines, which occur with YAML - # flow-type scalars (|, |- for example) - for name, policy in self.syaml.get("vaultPolicies", {}).items(): - policies[name] = self._sanitize_yaml_value(policy) - - return policies - - def _get_secrets(self): - return self.syaml.get("secrets", {}) - - def _get_field_on_missing_value(self, f): - # By default if 'onMissingValue' is missing we assume we need to - # error out whenever the value is missing - return f.get("onMissingValue", "error") - - def _get_field_value(self, f): - return f.get("value", None) - - def _get_field_path(self, f): - return f.get("path", None) - - def _get_field_ini_file(self, f): - return f.get("ini_file", None) - - def _get_field_annotations(self, f): - return f.get("annotations", {}) - - def _get_field_labels(self, f): - return f.get("labels", {}) - - def _get_field_kind(self, f): - # value: null will be interpreted with None, so let's just - # check for the existence of the field, as we use 'value: null' to say - # "we want a value/secret and not a file path" - found = [] - for i in ["value", "path", "ini_file"]: - if i in f: - found.append(i) - - if len(found) > 1: # you can only have one of value, path and ini_file - self.module.fail_json( - f"Both '{found[0]}' and '{found[1]}' cannot be used " - f"in field {f['name']}" - ) - - if len(found) == 0: - return "" - return found[0] - - def _get_field_prompt(self, f): - return f.get("prompt", None) - - def _get_field_base64(self, f): - return bool(f.get("base64", False)) - - def _get_field_override(self, f): - return bool(f.get("override", False)) - - def _get_secret_store_namespace(self): - return str(self.syaml.get("secretStoreNamespace", secret_store_namespace)) - - def _get_vault_prefixes(self, s): - return list(s.get("vaultPrefixes", ["hub"])) - - def _get_default_labels(self): - return self.syaml.get("defaultLabels", {}) - - def _get_default_annotations(self): - return self.syaml.get("defaultAnnotations", {}) - - def _append_kubernetes_secret(self, secret_obj): - self.kubernetes_secret_objects.append(secret_obj) - - def _sanitize_yaml_value(self, value): - # This is useful for embedded newlines, which occur with YAML - # flow-type scalars (|, |- for example) - if value is not None: - sanitized_value = bytes(value, "utf-8").decode("unicode_escape") - else: - sanitized_value = None - - return sanitized_value - - def _create_k8s_secret(self, sname, secret_type, namespace, labels, annotations): - return { - "type": secret_type, - "kind": "Secret", - "apiVersion": "v1", - "metadata": { - "name": sname, - "namespace": namespace, - "annotations": annotations, - "labels": labels, - }, - "stringData": {}, - } - - # This does what inject_secrets used to (mostly) - def parse(self): - self.sanitize_values() - self.vault_policies = self._get_vault_policies() - self.secret_store_namespace = self._get_secret_store_namespace() - backing_store = self._get_backingstore() - secrets = self._get_secrets() - - total_secrets = 0 # Counter for all the secrets uploaded - for s in secrets: - total_secrets += 1 - counter = 0 # This counter is to use kv put on first secret and kv patch on latter - sname = s.get("name") - fields = s.get("fields", []) - vault_prefixes = self._get_vault_prefixes(s) - secret_type = s.get("type", "Opaque") - vault_mount = s.get("vaultMount", "secret") - target_namespaces = s.get("targetNamespaces", []) - labels = stringify_dict(s.get("labels", self._get_default_labels())) - annotations = stringify_dict( - s.get("annotations", self._get_default_annotations()) - ) - - self.parsed_secrets[sname] = { - "name": sname, - "fields": {}, - "vault_mount": vault_mount, - "vault_policies": {}, - "vault_prefixes": vault_prefixes, - "override": [], - "generate": [], - "paths": {}, - "base64": [], - "ini_file": {}, - "type": secret_type, - "target_namespaces": target_namespaces, - "labels": labels, - "annotations": annotations, - } - - for i in fields: - self._inject_field(sname, i) - counter += 1 - - if backing_store == "kubernetes": - k8s_namespaces = [self._get_secret_store_namespace()] - else: - k8s_namespaces = target_namespaces - - for tns in k8s_namespaces: - k8s_secret = self._create_k8s_secret( - sname, secret_type, tns, labels, annotations - ) - k8s_secret["stringData"] = self.parsed_secrets[sname]["fields"] - self.kubernetes_secret_objects.append(k8s_secret) - - return total_secrets - - # This function could use some rewriting and it should call a specific validation function - # for each type (value, path, ini_file) - def _validate_field(self, f): - # These fields are mandatory - try: - _ = f["name"] - except KeyError: - return (False, f"Field {f} is missing name") - - on_missing_value = self._get_field_on_missing_value(f) - if on_missing_value not in ["error", "generate", "prompt"]: - return (False, f"onMissingValue: {on_missing_value} is invalid") - - value = self._get_field_value(f) - path = self._get_field_path(f) - ini_file = self._get_field_ini_file(f) - kind = self._get_field_kind(f) - if kind == "ini_file": - # if we are using ini_file then at least ini_key needs to be defined - # ini_section defaults to 'default' when omitted - ini_key = f.get("ini_key", None) - if ini_key is None: - return ( - False, - "ini_file requires at least ini_key to be defined", - ) - - # Test if base64 is a correct boolean (defaults to False) - _ = self._get_field_base64(f) - _ = self._get_field_override(f) - - vault_policy = f.get("vaultPolicy", None) - if vault_policy is not None and vault_policy not in self._get_vault_policies(): - return ( - False, - f"Secret has vaultPolicy set to {vault_policy} but no such policy exists", - ) - - if on_missing_value in ["error"]: - if ( - (value is None or len(value) < 1) - and (path is None or len(path) < 1) - and (ini_file is None or len(ini_file) < 1) - ): - return ( - False, - "Secret has onMissingValue set to 'error' and has neither value nor path nor ini_file set", - ) - if path is not None and not os.path.isfile(os.path.expanduser(path)): - return (False, f"Field has non-existing path: {path}") - - if ini_file is not None and not os.path.isfile( - os.path.expanduser(ini_file) - ): - return (False, f"Field has non-existing ini_file: {ini_file}") - - if on_missing_value in ["prompt"]: - # When we prompt, the user needs to set one of the following: - # - value: null # prompt for a secret without a default value - # - value: 123 # prompt for a secret but use a default value - # - path: null # prompt for a file path without a default value - # - path: /tmp/ca.crt # prompt for a file path with a default value - if "value" not in f and "path" not in f: - return ( - False, - "Secret has onMissingValue set to 'prompt' but has no value nor path fields", - ) - - if "override" in f: - return ( - False, - "'override' attribute requires 'onMissingValue' to be set to 'generate'", - ) - - return (True, "") - - def _validate_secrets(self): - backing_store = self._get_backingstore() - secrets = self._get_secrets() - if len(secrets) == 0: - self.module.fail_json("No secrets found") - - names = [] - for s in secrets: - # These fields are mandatory - for i in ["name"]: - try: - _ = s[i] - except KeyError: - return (False, f"Secret {s['name']} is missing {i}") - names.append(s["name"]) - - vault_prefixes = s.get("vaultPrefixes", ["hub"]) - # This checks for the case when vaultPrefixes: is specified but empty - if vault_prefixes is None or len(vault_prefixes) == 0: - return (False, f"Secret {s['name']} has empty vaultPrefixes") - - namespaces = s.get("targetNamespaces", []) - if not isinstance(namespaces, list): - return (False, f"Secret {s['name']} targetNamespaces must be a list") - - if backing_store == "none" and namespaces == []: - return ( - False, - f"Secret {s['name']} targetNamespaces cannot be empty for secrets backend {backing_store}", - ) # noqa: E501 - - labels = s.get("labels", {}) - if not isinstance(labels, dict): - return (False, f"Secret {s['name']} labels must be a dictionary") - - annotations = s.get("annotations", {}) - if not isinstance(annotations, dict): - return (False, f"Secret {s['name']} annotations must be a dictionary") - - fields = s.get("fields", []) - if len(fields) == 0: - return (False, f"Secret {s['name']} does not have any fields") - - field_names = [] - for i in fields: - (ret, msg) = self._validate_field(i) - if not ret: - return (False, msg) - field_names.append(i["name"]) - field_dupes = find_dupes(field_names) - if len(field_dupes) > 0: - return (False, f"You cannot have duplicate field names: {field_dupes}") - - dupes = find_dupes(names) - if len(dupes) > 0: - return (False, f"You cannot have duplicate secret names: {dupes}") - return (True, "") - - def sanitize_values(self): - """ - Sanitizes the secrets YAML object version 2.0 - - Parameters: - - Returns: - Nothing: Updates self.syaml(obj) if needed - """ - v = get_version(self.syaml) - if v not in ["2.0"]: - self.module.fail_json(f"Version is not 2.0: {v}") - - backing_store = self._get_backingstore() - if backing_store not in [ - "kubernetes", - "vault", - "none", - ]: # we currently only support vault - self.module.fail_json( - f"Currently only the 'vault', 'kubernetes' and 'none' backingStores are supported: {backing_store}" - ) - - (ret, msg) = self._validate_secrets() - if not ret: - self.module.fail_json(msg) - - def _get_secret_value(self, name, field): - on_missing_value = self._get_field_on_missing_value(field) - # We cannot use match + case as RHEL8 has python 3.9 (it needs 3.10) - # We checked for errors in _validate_secrets() already - if on_missing_value == "error": - return self._sanitize_yaml_value(field.get("value")) - elif on_missing_value == "prompt": - prompt = self._get_field_prompt(field) - if prompt is None: - prompt = f"Type secret for {name}/{field['name']}: " - value = self._get_field_value(field) - if value is not None: - prompt += f" [{value}]" - prompt += ": " - return getpass.getpass(prompt) - return None - - def _get_file_path(self, name, field): - on_missing_value = self._get_field_on_missing_value(field) - if on_missing_value == "error": - return os.path.expanduser(field.get("path")) - elif on_missing_value == "prompt": - prompt = self._get_field_prompt(field) - path = self._get_field_path(field) - if path is None: - path = "" - - if prompt is None: - text = f"Type path for file {name}/{field['name']} [{path}]: " - else: - text = f"{prompt} [{path}]: " - - newpath = getpass.getpass(text) - if newpath == "": # Set the default if no string was entered - newpath = path - - if os.path.isfile(os.path.expanduser(newpath)): - return newpath - self.module.fail_json(f"File {newpath} not found, exiting") - - self.module.fail_json("File with wrong onMissingValue") - - def _inject_field(self, secret_name, f): - on_missing_value = self._get_field_on_missing_value(f) - override = self._get_field_override(f) - kind = self._get_field_kind(f) - b64 = self._get_field_base64(f) - - if kind in ["value", ""]: - if on_missing_value == "generate": - self.parsed_secrets[secret_name]["generate"].append(f["name"]) - if self._get_backingstore() != "vault": - self.module.fail_json( - "You cannot have onMissingValue set to 'generate' unless using vault backingstore " - f"for secret {secret_name} field {f['name']}" - ) - else: - if kind in ["path", "ini_file"]: - self.module.fail_json( - "You cannot have onMissingValue set to 'generate' with a path or ini_file" - f" for secret {secret_name} field {f['name']}" - ) - - vault_policy = f.get("vaultPolicy", "validatedPatternDefaultPolicy") - - if override: - self.parsed_secrets[secret_name]["override"].append(f["name"]) - - if b64: - self.parsed_secrets[secret_name]["base64"].append(f["name"]) - - self.parsed_secrets[secret_name]["fields"][f["name"]] = None - self.parsed_secrets[secret_name]["vault_policies"][ - f["name"] - ] = vault_policy - - return - - # If we're not generating the secret inside the vault directly we either read it from the file ("error") - # or we are prompting the user for it - secret = self._get_secret_value(secret_name, f) - if b64: - secret = base64.b64encode(secret.encode()).decode("utf-8") - self.parsed_secrets[secret_name]["base64"].append(f["name"]) - - self.parsed_secrets[secret_name]["fields"][f["name"]] = secret - - elif kind == "path": # path. we upload files - path = self._get_file_path(secret_name, f) - self.parsed_secrets[secret_name]["paths"][f["name"]] = path - - binfile = False - - # Default to UTF-8 - try: - secret = open(path, encoding="utf-8").read() - except UnicodeDecodeError: - secret = open(path, "rb").read() - binfile = True - - if b64: - self.parsed_secrets[secret_name]["base64"].append(f["name"]) - if binfile: - secret = base64.b64encode(bytes(secret)).decode("utf-8") - else: - secret = base64.b64encode(secret.encode()).decode("utf-8") - - self.parsed_secrets[secret_name]["fields"][f["name"]] = secret - elif kind == "ini_file": # ini_file. we parse an ini_file - ini_file = os.path.expanduser(f.get("ini_file")) - ini_section = f.get("ini_section", "default") - ini_key = f.get("ini_key") - secret = get_ini_value(ini_file, ini_section, ini_key) - if b64: - self.parsed_secrets[secret_name]["base64"].append(f["name"]) - secret = base64.b64encode(secret.encode()).decode("utf-8") - - self.parsed_secrets[secret_name]["ini_file"][f["name"]] = { - "ini_file": ini_file, - "ini_section": ini_section, - "ini_key": ini_key, - } - self.parsed_secrets[secret_name]["fields"][f["name"]] = secret - - return diff --git a/ansible/plugins/modules/parse_secrets_info.py b/ansible/plugins/modules/parse_secrets_info.py deleted file mode 100644 index b962271a..00000000 --- a/ansible/plugins/modules/parse_secrets_info.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright 2022,2023 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Ansible plugin module that loads secrets from a yaml file and pushes them -inside the HashiCorp Vault in an OCP cluster. The values-secrets.yaml file is -expected to be in the following format: ---- -# version is optional. When not specified it is assumed it is 1.0 -version: 1.0 - -# These secrets will be pushed in the vault at secret/hub/test The vault will -# have secret/hub/test with secret1 and secret2 as keys with their associated -# values (secrets) -secrets: - test: - secret1: foo - secret2: bar - -# This will create the vault key secret/hub/testfoo which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files: - testfoo: ~/ca.crt - -# These secrets will be pushed in the vault at secret/region1/test The vault will -# have secret/region1/test with secret1 and secret2 as keys with their associated -# values (secrets) -secrets.region1: - test: - secret1: foo1 - secret2: bar1 - -# This will create the vault key secret/region2/testbar which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files.region2: - testbar: ~/ca.crt -""" - -import yaml -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.parse_secrets_v2 import ParseSecretsV2 - -ANSIBLE_METADATA = { - "metadata_version": "1.2", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: parse_secrets_info -short_description: Parses a Validated Patterns Secrets file for later loading -version_added: "2.50" -author: "Martin Jackson" -description: - - Takes a values-secret.yaml file, parses and returns values for secrets loading. The goal here is to do all the - work of reading and interpreting the file and resolving the content pointers (that is, creating content where it - is given) such that that content is then available for secrets vaults to load. It does not attempt to load the - content or interpret the content beyond the conventions of the file format. (So, it knows how to retrieve - ini-keys, about paths, and about base64 but leaves interaction with backends to backend-specific code. -options: - values_secrets_plaintext: - description: - - The unencrypted content of the values-secrets file - required: true - type: str - secrets_backing_store: - description: - - The secrets backing store that will be used for parsed secrets (i.e. vault, kubernetes, none) - required: false - default: vault - type: str -""" - -RETURN = """ -""" - -EXAMPLES = """ -- name: Parse secrets file into objects - backingstore defaults to vault - parse_secrets_info: - values_secrets_plaintext: '{{ }}' - register: secrets_info - -- name: Parse secrets file into data structures - parse_secrets_info: - values_secrets_plaintext: '{{ }}' - secrets_backing_store: 'kubernetes' - register: secrets_info - -- name: Parse secrets file into data structures - parse_secrets_info: - values_secrets_plaintext: '{{ }}' - secrets_backing_store: 'none' - register: secrets_info -""" - - -def run(module): - """Main ansible module entry point""" - results = dict(changed=False) - - args = module.params - values_secrets_plaintext = args.get("values_secrets_plaintext", "") - secrets_backing_store = args.get("secrets_backing_store", "vault") - - syaml = yaml.safe_load(values_secrets_plaintext) - - if syaml is None: - syaml = {} - - parsed_secret_obj = ParseSecretsV2(module, syaml, secrets_backing_store) - parsed_secret_obj.parse() - - results["failed"] = False - results["changed"] = False - - results["vault_policies"] = parsed_secret_obj.vault_policies - results["parsed_secrets"] = parsed_secret_obj.parsed_secrets - results["kubernetes_secret_objects"] = parsed_secret_obj.kubernetes_secret_objects - results["secret_store_namespace"] = parsed_secret_obj.secret_store_namespace - - module.exit_json(**results) - - -def main(): - """Main entry point where the AnsibleModule class is instantiated""" - module = AnsibleModule( - argument_spec=yaml.safe_load(DOCUMENTATION)["options"], - supports_check_mode=True, - ) - run(module) - - -if __name__ == "__main__": - main() diff --git a/ansible/plugins/modules/vault_load_parsed_secrets.py b/ansible/plugins/modules/vault_load_parsed_secrets.py deleted file mode 100644 index f5acdc86..00000000 --- a/ansible/plugins/modules/vault_load_parsed_secrets.py +++ /dev/null @@ -1,303 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Ansible plugin module that loads secrets and policies once parsed and pushes them -into a HashiCorp Vault in an OCP cluster. The values-secrets.yaml file is -expected to be in the following format: ---- -# version is optional. When not specified it is assumed it is 2.0 -version: 2.0 - -""" - -import os -import time - -import yaml -from ansible.module_utils.basic import AnsibleModule - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: vault_load_parsed_secrets -short_description: Loads secrets into the HashiCorp Vault -version_added: "2.50" -author: "Martin Jackson" -description: - - Takes parsed secrets objects and vault policies (as delivered by parse_secrets_info) and runs the commands to - load them into a vault instance. The relevent metadata will exist in the parsed secrets object. Returns count - of secrets injected. -options: - parsed_secrets: - description: - - A structure containing the secrets, fields, and their metadata - required: true - type: dict - vault_policies: - description: - - Vault policies to inject into the instance. - required: true - type: dict - namespace: - description: - - Namespace where the vault is running - required: false - type: str - default: vault - pod: - description: - - Name of the vault pod to use to inject secrets - required: false - type: str - default: vault-0 -""" - -RETURN = """ -""" - -EXAMPLES = """ -- name: Loads secrets file into the vault of a cluster - vault_load_parsed_secrets: - parsed_secrets: "{{ parsed_secrets_structure_from_parse_secrets_info }}" - vault_policies: "{{ parsed_vault_policies_structure_from_parse_secrets_info }}" -""" - - -class VaultSecretLoader: - - def __init__( - self, - module, - parsed_secrets, - vault_policies, - namespace, - pod, - ): - self.module = module - self.parsed_secrets = parsed_secrets - self.vault_policies = vault_policies - self.namespace = namespace - self.pod = pod - - def _run_command(self, command, attempts=1, sleep=3, checkrc=True): - """ - Runs a command on the host ansible is running on. A failing command - will raise an exception in this function directly (due to check=True) - - Parameters: - command(str): The command to be run. - attempts(int): Number of times to retry in case of Error (defaults to 1) - sleep(int): Number of seconds to wait in between retry attempts (defaults to 3s) - - Returns: - ret(subprocess.CompletedProcess): The return value from run() - """ - for attempt in range(attempts): - ret = self.module.run_command( - command, - check_rc=checkrc, - use_unsafe_shell=True, - environ_update=os.environ.copy(), - ) - if ret[0] == 0: - return ret - if attempt >= attempts - 1: - return ret - time.sleep(sleep) - - def _vault_secret_attr_exists(self, mount, prefix, secret_name, attribute): - cmd = ( - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f'"vault kv get -mount={mount} -field={attribute} {prefix}/{secret_name}"' - ) - # we ignore stdout and stderr - (ret, _, _) = self._run_command(cmd, attempts=1, checkrc=False) - if ret == 0: - return True - - return False - - def load_vault(self): - injected_secret_count = 0 - - self.inject_vault_policies() - - for secret_name, secret in self.parsed_secrets.items(): - self.inject_secret(secret_name, secret) - injected_secret_count += 1 - - return injected_secret_count - - def inject_field( - self, - secret_name, - soverride, - sbase64, - sgenerate, - spaths, - svault_policies, - fieldname, - fieldvalue, - mount, - vault_prefixes, - first=False, - ): - # Special cases: - # generate w|wo override - # path (w|wo b64) - # - # inifile secrets will be resolved by parser - # values (including base64'd ones) will be resolved by parser - # And we just ignore k8s or other fields - - override = True if fieldname in soverride else False - b64 = True if fieldname in sbase64 else False - generate = True if fieldname in sgenerate else False - path = spaths.get(fieldname, False) - prefixes = vault_prefixes - verb = "put" if first else "patch" - policy = svault_policies.get(fieldname, False) - - # "generate" secrets are created with policies and may be overridden or not - if generate: - gen_cmd = ( - f"vault read -field=password sys/policies/password/{policy}/generate" - ) - if b64: - gen_cmd += " | base64 --wrap=0" - for prefix in prefixes: - # if the override field is False and the secret attribute exists at the prefix then we just - # skip, as we do not want to overwrite the existing secret - if not override and self._vault_secret_attr_exists( - mount, prefix, secret_name, fieldname - ): - continue - cmd = ( - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f'"{gen_cmd} | vault kv {verb} -mount={mount} {prefix}/{secret_name} {fieldname}=-"' - ) - self._run_command(cmd, attempts=3) - return - - if path: - for prefix in prefixes: - if b64: - b64_cmd = "| base64 --wrap=0" - else: - b64_cmd = "" - cmd = ( - f"cat '{path}' | oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"'cat - {b64_cmd}> /tmp/vcontent'; " - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c '" - f"vault kv {verb} -mount={mount} {prefix}/{secret_name} {fieldname}=@/tmp/vcontent; " - f"rm /tmp/vcontent'" - ) - self._run_command(cmd, attempts=3) - return - - for prefix in prefixes: - cmd = ( - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"\"vault kv {verb} -mount={mount} {prefix}/{secret_name} {fieldname}='\"'{fieldvalue}'\"'\"" - ) - self._run_command(cmd, attempts=3) - return - - def inject_secret(self, secret_name, secret): - mount = secret.get("vault_mount", "secret") - vault_prefixes = secret.get("vault_prefixes", ["hub"]) - - counter = 0 - # In this structure, each field will have one value - for fname, fvalue in secret.get("fields").items(): - self.inject_field( - secret_name=secret_name, - soverride=secret["override"], - sbase64=secret["base64"], - sgenerate=secret["generate"], - spaths=secret["paths"], - svault_policies=secret["vault_policies"], - fieldname=fname, - fieldvalue=fvalue, - mount=mount, - vault_prefixes=vault_prefixes, - first=counter == 0, - ) - counter += 1 - return - - def inject_vault_policies(self): - for name, policy in self.vault_policies.items(): - cmd = ( - f"echo '{policy}' | oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"'cat - > /tmp/{name}.hcl';" - f"oc exec -n {self.namespace} {self.pod} -i -- sh -c 'vault write sys/policies/password/{name} " - f" policy=@/tmp/{name}.hcl'" - ) - self._run_command(cmd, attempts=3) - - -def run(module): - """Main ansible module entry point""" - results = dict(changed=False) - - args = module.params - - vault_policies = args.get("vault_policies", {}) - parsed_secrets = args.get("parsed_secrets", {}) - namespace = args.get("namespace", "vault") - pod = args.get("pod", "vault-0") - - if vault_policies == {}: - results["failed"] = True - module.fail_json("Must pass vault_policies") - - if parsed_secrets == {}: - results["failed"] = True - module.fail_json("Must pass parsed_secrets") - - loader = VaultSecretLoader( - module, - parsed_secrets, - vault_policies, - namespace, - pod, - ) - - nr_secrets = loader.load_vault() - - results["failed"] = False - results["changed"] = True - results["msg"] = f"{nr_secrets} secrets injected" - module.exit_json(**results) - - -def main(): - """Main entry point where the AnsibleModule class is instantiated""" - module = AnsibleModule( - argument_spec=yaml.safe_load(DOCUMENTATION)["options"], - supports_check_mode=False, - ) - run(module) - - -if __name__ == "__main__": - main() diff --git a/ansible/plugins/modules/vault_load_secrets.py b/ansible/plugins/modules/vault_load_secrets.py deleted file mode 100644 index 725b69b4..00000000 --- a/ansible/plugins/modules/vault_load_secrets.py +++ /dev/null @@ -1,209 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Ansible plugin module that loads secrets from a yaml file and pushes them -inside the HashiCorp Vault in an OCP cluster. The values-secrets.yaml file is -expected to be in the following format: ---- -# version is optional. When not specified it is assumed it is 1.0 -version: 1.0 - -# These secrets will be pushed in the vault at secret/hub/test The vault will -# have secret/hub/test with secret1 and secret2 as keys with their associated -# values (secrets) -secrets: - test: - secret1: foo - secret2: bar - -# This will create the vault key secret/hub/testfoo which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files: - testfoo: ~/ca.crt - -# These secrets will be pushed in the vault at secret/region1/test The vault will -# have secret/region1/test with secret1 and secret2 as keys with their associated -# values (secrets) -secrets.region1: - test: - secret1: foo1 - secret2: bar1 - -# This will create the vault key secret/region2/testbar which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files.region2: - testbar: ~/ca.crt -""" - -import os - -import yaml -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.load_secrets_common import get_version -from ansible.module_utils.load_secrets_v1 import LoadSecretsV1 -from ansible.module_utils.load_secrets_v2 import LoadSecretsV2 - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: vault_load_secrets -short_description: Loads secrets into the HashiCorp Vault -version_added: "2.11" -author: "Michele Baldessari" -description: - - Takes a values-secret.yaml file and uploads the secrets into the HashiCorp Vault -options: - values_secrets: - description: - - Path to the values-secrets file (only one of values_secrets and - values_secrets_plaintext can be passed) - required: false - default: '' - type: str - values_secrets_plaintext: - description: - - The content of the values-secrets file (only one of values_secrets and - values_secrets_plaintext can be passed) - required: false - default: '' - type: str - namespace: - description: - - Namespace where the vault is running - required: false - type: str - default: vault - pod: - description: - - Name of the vault pod to use to inject secrets - required: false - type: str - default: vault-0 - basepath: - description: - - Vault's kv initial part of the path. This is only supported on version 1.0 of the - secret format - required: false - type: str - default: secret - check_missing_secrets: - description: - - Validate the ~/values-secret.yaml file against the top-level - values-secret-template.yaml and error out if secrets are missing - required: false - type: bool - default: False - values_secret_template: - description: - - Path of the values-secret-template.yaml file of the pattern - required: false - type: str - default: "" -""" - -RETURN = """ -""" - -EXAMPLES = """ -- name: Loads secrets file into the vault of a cluster - vault_load_secrets: - values_secrets: ~/values-secret.yaml -""" - - -def run(module): - """Main ansible module entry point""" - results = dict(changed=False) - - args = module.params - values_secrets = os.path.expanduser(args.get("values_secrets", "")) - values_secrets_plaintext = args.get("values_secrets_plaintext", "") - if values_secrets != "" and values_secrets_plaintext != "": - module.fail_json("Cannot pass both values_secret and values_secret_plaintext") - - values_secrets = os.path.expanduser(args.get("values_secrets")) - basepath = args.get("basepath") - namespace = args.get("namespace") - pod = args.get("pod") - check_missing_secrets = args.get("check_missing_secrets") - values_secret_template = args.get("values_secret_template") - - if values_secrets != "" and not os.path.exists(values_secrets): - results["failed"] = True - results["error"] = f"Missing {values_secrets} file" - results["msg"] = f"Values secrets file does not exist: {values_secrets}" - module.exit_json(**results) - - # We were passed a filename (aka the unencrypted path) - if values_secrets != "": - with open(values_secrets, "r", encoding="utf-8") as file: - syaml = yaml.safe_load(file.read()) - if syaml is None: - syaml = {} - elif isinstance(syaml, str): - module.fail_json(f"Could not parse {values_secrets} file as yaml") - elif values_secrets_plaintext != "": - syaml = yaml.safe_load(values_secrets_plaintext) - if syaml is None: - syaml = {} - elif isinstance(syaml, str): - module.fail_json("Could not parse values_secrets_plaintext as yaml") - else: - module.fail_json("Both values_secrets and values_secrets_plaintext are unset") - - version = get_version(syaml) - if version == "2.0": - secret_obj = LoadSecretsV2(module, syaml, namespace, pod) - elif version == "1.0": - secret_obj = LoadSecretsV1( - module, - syaml, - basepath, - namespace, - pod, - values_secret_template, - check_missing_secrets, - ) - - else: - module.fail_json(f"Version {version} is currently not supported") - - secret_obj.sanitize_values() - nr_secrets = secret_obj.inject_secrets() - results["failed"] = False - results["changed"] = True - results["msg"] = f"{nr_secrets} secrets injected" - module.exit_json(**results) - - -def main(): - """Main entry point where the AnsibleModule class is instantiated""" - module = AnsibleModule( - argument_spec=yaml.safe_load(DOCUMENTATION)["options"], - supports_check_mode=False, - ) - run(module) - - -if __name__ == "__main__": - main() diff --git a/ansible/roles/cluster_pre_check/defaults/main.yml b/ansible/roles/cluster_pre_check/defaults/main.yml deleted file mode 100644 index fd6cdd5c..00000000 --- a/ansible/roles/cluster_pre_check/defaults/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" -kubeconfig_backup: "{{ lookup('env', 'HOME') }}/.kube/config" diff --git a/ansible/roles/cluster_pre_check/tasks/main.yml b/ansible/roles/cluster_pre_check/tasks/main.yml deleted file mode 100644 index 1dc5f445..00000000 --- a/ansible/roles/cluster_pre_check/tasks/main.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -- name: Check if the kubernetes python module is usable from ansible - ansible.builtin.command: "{{ ansible_python_interpreter }} -c 'import kubernetes'" - changed_when: false - -- name: Check if KUBECONFIG is correctly set - ansible.builtin.debug: - msg: "KUBECONFIG is not set, falling back to ~/.kube/config" - when: kubeconfig is not defined or kubeconfig | length == 0 - -- name: Check if ~/.kube/config exists - ansible.builtin.stat: - path: "{{ kubeconfig_backup }}" - register: kubeconfig_result - -- name: Check if we're running inside an OCP cluster directly - ansible.builtin.set_fact: - running_in_ocp: "{{ lookup('env', 'KUBERNETES_SERVICE_HOST') | length > 0 | bool }}" - -- name: Fail if both KUBECONFIG and ~/.kube/config do not exist but only when not running in a cluster - ansible.builtin.fail: - msg: "{{ kubeconfig_backup }} not found and KUBECONFIG unset. Bailing out." - failed_when: - - not running_in_ocp - - not kubeconfig_result.stat.exists - - kubeconfig is not defined or kubeconfig | length == 0 diff --git a/ansible/roles/find_vp_secrets/tasks/main.yml b/ansible/roles/find_vp_secrets/tasks/main.yml deleted file mode 100644 index ce847a01..00000000 --- a/ansible/roles/find_vp_secrets/tasks/main.yml +++ /dev/null @@ -1,87 +0,0 @@ ---- -# Once V1 support is dropped we can remove the whole secret_template support -- name: Set secret_template fact - no_log: "{{ override_no_log | default(true) }}" - ansible.builtin.set_fact: - secret_template: "{{ pattern_dir }}/values-secret.yaml.template" - -- name: Is a VALUES_SECRET env variable set? - ansible.builtin.set_fact: - custom_env_values_secret: "{{ lookup('ansible.builtin.env', 'VALUES_SECRET') }}" - -- name: Check if VALUES_SECRET file exists - ansible.builtin.stat: - path: "{{ custom_env_values_secret }}" - register: custom_file_values_secret - when: custom_env_values_secret | default('') | length > 0 - -- name: Set values-secret yaml file to {{ custom_file_values_secret.stat.path }} - ansible.builtin.set_fact: - found_file: "{{ custom_file_values_secret.stat.path }}" - when: - - custom_env_values_secret | default('') | length > 0 - - custom_file_values_secret.stat.exists - -# FIXME(bandini): Eventually around end of 2023(?) we should drop -# ~/values-secret-{{ pattern_name }}.yaml and ~/values-secret.yaml -- name: Find first existing values-secret yaml file - ansible.builtin.set_fact: - found_file: "{{ lookup('ansible.builtin.first_found', findme) }}" - vars: - findme: - - "~/.config/hybrid-cloud-patterns/values-secret-{{ pattern_name }}.yaml" - - "~/.config/validated-patterns/values-secret-{{ pattern_name }}.yaml" - - "~/values-secret-{{ pattern_name }}.yaml" - - "~/values-secret.yaml" - - "{{ pattern_dir }}/values-secret.yaml.template" - when: custom_env_values_secret | default('') | length == 0 - -- name: Is found values secret file encrypted - no_log: "{{ override_no_log | default(true) }}" - ansible.builtin.shell: | - set -o pipefail - head -1 "{{ found_file }}" | grep -q \$ANSIBLE_VAULT - changed_when: false - register: encrypted - failed_when: (encrypted.rc not in [0, 1]) - -# When HOME is set we replace it with '~' in this debug message -# because when run from inside the container the HOME is /pattern-home -# which is confusing for users -- name: Is found values secret file encrypted - ansible.builtin.debug: - msg: "Using {{ (lookup('env', 'HOME') | length > 0) | ternary(found_file | regex_replace('^' + lookup('env', 'HOME'), '~'), found_file) }} to parse secrets" - -- name: Set encryption bool fact - no_log: "{{ override_no_log | default(true) }}" - ansible.builtin.set_fact: - is_encrypted: "{{ encrypted.rc == 0 | bool }}" - -- name: Get password for "{{ found_file }}" - ansible.builtin.pause: - prompt: "Input the password for {{ found_file }}" - echo: false - when: is_encrypted - register: vault_pass - -- name: Get decrypted content if {{ found_file }} was encrypted - no_log: "{{ override_no_log | default(true) }}" - ansible.builtin.shell: - ansible-vault view --vault-password-file <(cat <<<"{{ vault_pass.user_input }}") "{{ found_file }}" - register: values_secret_plaintext - when: is_encrypted - changed_when: false - -- name: Normalize secrets format (un-encrypted) - no_log: '{{ override_no_log | default(true) }}' - ansible.builtin.set_fact: - values_secrets_data: "{{ lookup('file', found_file) | from_yaml }}" - when: not is_encrypted - changed_when: false - -- name: Normalize secrets format (encrypted) - no_log: '{{ override_no_log | default(true) }}' - ansible.builtin.set_fact: - values_secrets_data: "{{ values_secret_plaintext.stdout | from_yaml }}" - when: is_encrypted - changed_when: false diff --git a/ansible/roles/iib_ci/README.md b/ansible/roles/iib_ci/README.md deleted file mode 100644 index de4b4107..00000000 --- a/ansible/roles/iib_ci/README.md +++ /dev/null @@ -1,111 +0,0 @@ -# IIB Utilities - -A set of ansible plays to fetch an IIB (Image Index Bundle, aka a container created by the operator SDK -that contains a bunch of references to operators that can be installed in an OpenShift cluster) - -Run `ansible-playbook common/ansible/playbooks/iib-ci/lookup.yml` to see which IIBs are available (defaults to -openshift-gitops). If you want to look up IIBs for a different operator run: -`ansible-playbook -e operator=acm-operator common/ansible/playbooks/iib-ci/lookup.yml` - -You can also try running curl manually via: -`curl -sSL "https://datagrepper.engineering.redhat.com/raw?topic=/topic/VirtualTopic.eng.ci.redhat-container-image.index.built&delta=15780000&contains=acm-operator" | jq ".raw_messages[].msg"` - -Typically IIB are prerelease stuff that lives on some internal boxes. What these scripts do is fetch -the IIB internally, mirror it to the registry inside the cluster, parse all the needed images and mirror -those to the internal cluster registry and then set up the registries.conf files on all nodes so -that the images used are the ones pointing to the internal cluster. - -## Usage - -By default the operator to be installed from the IIB is `openshift-gitops-operator`. You can override this through the `OPERATOR` env variable. -For example, to mirror an operator into an existing cluster you would do the following: - -```sh -export KUBECONFIG=/tmp/foo/kubeconfig -export OPERATOR=openshift-gitops-operator -export IIB=492329 -export INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:${IIB} -export KUBEADMINPASS="11111-22222-33333-44444" -# This will push the IIB and all the needed images for the default openshift-gitops-operator into the cluster -make load-iib -# This will install the pattern using the gitops operator from the IIB -``` - -***NOTE:*** When using an SNO without shared storage in a non-production environment, the enablement of the internal registry will fail. You need to run the following to enable it: - -```sh -oc patch configs.imageregistry.operator.openshift.io cluster --type merge --patch '{"spec":{"managementState":"Managed"}}' -oc patch configs.imageregistry.operator.openshift.io cluster --type merge --patch '{"spec":{"storage":{"emptyDir":{}}}}' -``` - -### Gitops operator - -Then in case of the `openshift-gitops-operator` we would install with: - -```sh -export CHANNEL=$(oc get -n openshift-marketplace packagemanifests -l "catalog=iib-${IIB}" --field-selector "metadata.name=${OPERATOR}" -o jsonpath='{.items[0].status.defaultChannel}') -make EXTRA_HELM_OPTS="--set main.gitops.operatorSource=iib-${IIB} --set main.gitops.channel=${CHANNEL}" install -``` - -### ACM operator - -The advanced-cluster-management operator is a little bit more complex than the others because it -also installes another operator called MCE multicluster-engine. So to install ACM you typically -need two IIBs (one for acm and one for mce). With those two at hand, do the following (the ordering must be -consistent: the first IIB corresponds to the first OPERATOR, etc). The following operation needs to be done -on both hub *and* spokes: - -```sh -for i in hub-kubeconfig-file spoke-kubeconfig-file; do - export KUBECONFIG="${i}" - export KUBEADMINPASS="11111-22222-33333-44444" - export OPERATOR=advanced-cluster-management,multicluster-engine - export INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:713808,registry-proxy.engineering.redhat.com/rh-osbs/iib:718034 - make load-iib -done -``` - -Once the IIBs are loaded into the cluster we need to run the following steps: - -```sh -export ACM_CHANNEL=$(oc get -n openshift-marketplace packagemanifests -l "catalog=iib-713808" --field-selector "metadata.name=advanced-cluster-management" -o jsonpath='{.items[0].status.defaultChannel}') -export MCE_CHANNEL=$(oc get -n openshift-margetplace packagemanifests -l "catalog=iib-718034" --field-selector "metadata.name=multicluster-engine" -o jsonpath='{.items[0].status.defaultChannel}') -make EXTRA_HELM_OPTS="--set main.extraParameters[0].name=clusterGroup.subscriptions.acm.source --set main.extraParameters[0].value=iib-713808 \ - --set main.extraParameters[1].name=clusterGroup.subscriptions.acm.channel --set main.extraParameters[1].value=${ACM_CHANNEL} \ - --set main.extraParameters[2].name=acm.mce_operator.source --set main.extraParameters[2].value="iib-718034" \ - --set main.extraParameters[3].name=acm.mce_operator.channel --set main.extraParameters[3].value=${MCE_CHANNEL}" install -``` - -*Note*: In this case the `acm` in `clusterGroup.subscriptions.acm.*` is the name of the key in the subscriptions in `values-hub.yaml` - -### Other operators - -To install operators other than gitops and acm do the following: - -```sh -export CHANNEL=$(oc get -n openshift-marketplace packagemanifests -l "catalog=iib-${IIB}" --field-selector "metadata.name=${OPERATOR}" -o jsonpath='{.items[0].status.defaultChannel}') -make EXTRA_HELM_OPTS="--set main.extraParameters[0].name=clusterGroup.subscriptions..source --set main.extraParameters[0].value=iib-${IIB} --set main.extraParameters[1].name=clusterGroup.subscriptions..channel --set main.extraParameters[1].value=${CHANNEL}" install -``` - -*Note*: Replace `` with the actual name of the subscription dictionary in `values-hub.yaml` - -## Useful commands - -* List IIBs for an operator: - -```sh -ansible-playbook common/ansible/playbooks/iib-ci/lookup.yml -... -ok: [localhost] => (item=v4.13) => { - "msg": "v4.13 -> {'indeximage': 'registry-proxy.engineering.redhat.com/rh-osbs/iib:509435', 'bundleimage': 'registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-gitops-operator-bundle:v99.9.0-106'}" -} -... -``` - -Override the `operator` value with the desired bundle name to figure out the last IIBs for it. - -* List all images uploaded to the internal registry: - -```sh -oc exec -it -n openshift-image-registry $(oc get pods -n openshift-image-registry -o json | jq -r '.items[].metadata.name | select(. | test("^image-registry-"))' | head -n1) -- bash -c "curl -k -u kubeadmin:$(oc whoami -t) https://localhost:5000/v2/_catalog" -``` diff --git a/ansible/roles/iib_ci/defaults/main.yml b/ansible/roles/iib_ci/defaults/main.yml deleted file mode 100644 index 397be608..00000000 --- a/ansible/roles/iib_ci/defaults/main.yml +++ /dev/null @@ -1,13 +0,0 @@ -rh_internal_registry: registry-proxy.engineering.redhat.com -iib_images: "{{ lookup('env', 'INDEX_IMAGES') }}" - -kubeadminpass: "{{ lookup('env', 'KUBEADMINPASS') }}" - -internal_registry_ns: openshift-marketplace -internal_registry_email: noemail@localhost -internal_registry_user: registry-custom-user -internal_registry_pass: "{{ lookup('env', 'INTERNAL_REGISTRY_USER') }}" - -# We can use default(, true) below because OPERATOR is a string and not -# a boolean -operator: "{{ lookup('env', 'OPERATOR') | default('openshift-gitops-operator', true) }}" diff --git a/ansible/roles/iib_ci/handlers/main.yml b/ansible/roles/iib_ci/handlers/main.yml deleted file mode 100644 index a983544d..00000000 --- a/ansible/roles/iib_ci/handlers/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# handlers file for vault_utils diff --git a/ansible/roles/iib_ci/meta/main.yml b/ansible/roles/iib_ci/meta/main.yml deleted file mode 100644 index c9d7005d..00000000 --- a/ansible/roles/iib_ci/meta/main.yml +++ /dev/null @@ -1,29 +0,0 @@ -galaxy_info: - author: Validated Patterns Team https://github.com/hybrid-cloud-patterns/ - description: Internal module to work with IIBs (Image Index Bundles) - - issue_tracker_url: https://github.com/hybrid-cloud-patterns/common/issues - license: Apache-2.0 - min_ansible_version: "2.1" - - # If this a Container Enabled role, provide the minimum Ansible Container version. - # min_ansible_container_version: - - platforms: - - name: Fedora - versions: - - all - - name: Ubuntu - versions: - - all - - name: Debian - versions: - - all - - name: EL - versions: - - "8" - - "9" - - galaxy_tags: [] - -dependencies: [] diff --git a/ansible/roles/iib_ci/tasks/fetch-operator-images.yml b/ansible/roles/iib_ci/tasks/fetch-operator-images.yml deleted file mode 100644 index 391f2ac2..00000000 --- a/ansible/roles/iib_ci/tasks/fetch-operator-images.yml +++ /dev/null @@ -1,102 +0,0 @@ -# This task fetches all the images given an operator name -# the operator name is defined in the variable "item". This -# set of tasks is to be included in a loop that goes over the -# needed operators -- name: Get default channel in the IIB for "{{ item.key }}" - ansible.builtin.shell: | - oc get -n "{{ internal_registry_ns }}" packagemanifests -l "catalog=iib-{{ item.value['iib'] }}" --field-selector "metadata.name={{ item.key }}" \ - -o jsonpath='{.items[0].status.defaultChannel}' - register: default_channel_raw - retries: 10 - delay: 10 - until: default_channel_raw is not failed - -- name: Set default channel fact - ansible.builtin.set_fact: - default_channel: "{{ default_channel_raw.stdout }}" - -- name: Print default channel - ansible.builtin.debug: - msg: "Default channel for {{ item.key }}: {{ default_channel }}" - -- name: Get all related images in the IIB for "{{ item.key }}" - ansible.builtin.shell: | - oc get packagemanifests -l "catalog=iib-{{ item.value['iib'] }}" --field-selector "metadata.name={{ item.key }}" \ - -o jsonpath="{.items[0].status.channels[?(@.name==\"{{ default_channel }}\")].currentCSVDesc.relatedImages}" - register: related_images_raw - retries: 5 - delay: 10 - until: related_images_raw is not failed - -- name: Set related_images fact - ansible.builtin.set_fact: - related_images: "{{ related_images_raw.stdout }}" - -# NOTE(bandini) -# The following code is here to find out what the operator bundle image is and to make -# sure it is on the internal registry. -# This is all potentially hacky, but so far I could not find a single place in the cluster -# where the olm.bundle image is available. The info is in there in the IIB, but it certainly -# is not in any package manifest nor catalogsource. This is why we resort to invoking opm -# alpha commands inside the IIB image locally -- name: Pull the IIB locally - ansible.builtin.command: - podman pull "{{ item.value['iib_image'] }}" - -# $ opm alpha list channels /configs advanced-cluster-management -# PACKAGE CHANNEL HEAD -# advanced-cluster-management release-2.7 advanced-cluster-management.v2.7.4 -# advanced-cluster-management release-2.8 advanced-cluster-management.v2.8.0-130 -- name: Read the operator bundle from the default channel - ansible.builtin.shell: | - set -o pipefail - podman run -it --rm "{{ item.value['iib_image'] }}" alpha list channels /configs "{{ item.key }}" | grep -E "(\s){{ default_channel }}(\s)" | awk '{ print $3 }' - register: bundle_channel_raw - -- name: Set bundle fact - ansible.builtin.set_fact: - bundle_channel: "{{ bundle_channel_raw.stdout }}" - -- name: Fail if bundle_channel is empty - ansible.builtin.fail: - msg: "Failed to find bundle from channel: {{ bundle_channel_raw }}" - when: > - (bundle_channel is not defined) or (bundle_channel | length == 0) - -# $ opm alpha list bundles /configs advanced-cluster-management -# PACKAGE CHANNEL BUNDLE REPLACES SKIPS SKIP RANGE IMAGE -# advanced-cluster-management release-2.7 advanced-cluster-management.v2.7.0 >=2.6.0 <2.7.0 registry.stage.redhat.io/rhacm2/acm-operator-bundle@sha256:f63d0a9a0e3dc9d86e84279c50e9c613d8430e71a3821d418e168250ca3b747c -# advanced-cluster-management release-2.7 advanced-cluster-management.v2.7.1 advanced-cluster-management.v2.7.0 >=2.6.0 <2.7.1 registry.stage.redhat.io/rhacm2/acm-operator-bundle@sha256:a81a574f2f22d37681c44fe0c3b958074408705415de333de54d120145537533 -# advanced-cluster-management release-2.7 advanced-cluster-management.v2.7.2 advanced-cluster-management.v2.7.1 >=2.6.0 <2.7.2 registry.stage.redhat.io/rhacm2/acm-operator-bundle@sha256:8a2c758689eaebe6a287315ca18fd9122f323e195ea3410db005b6a449060fad -# advanced-cluster-management release-2.7 advanced-cluster-management.v2.7.3 advanced-cluster-management.v2.7.2 >=2.6.0 <2.7.3 registry.stage.redhat.io/rhacm2/acm-operator-bundle@sha256:208f4d9473a923817c102bb7e5f138d3e1e8ed3057a23a220ffa8fe9c0c27128 -# advanced-cluster-management release-2.7 advanced-cluster-management.v2.7.4 advanced-cluster-management.v2.7.3 >=2.6.0 <2.7.4 registry.stage.redhat.io/rhacm2/acm-operator-bundle@sha256:75b6438e08800b2e3608aeb01c1c0a68810108d9905fff35916afd21e6d32685 -# advanced-cluster-management release-2.8 advanced-cluster-management.v2.8.0-130 >=2.7.0 <2.8.0-130 registry.stage.redhat.io/rhacm2/acm-operator-bundle@sha256:6c385aa69256cdd964ae9e79e52ce52e1048391f0557af59843326c4ebe9bec0 -- name: Get bundle image - ansible.builtin.shell: | - set -o pipefail - podman run -it --rm "{{ item.value['iib_image'] }}" alpha list bundles /configs "{{ item.key }}" | grep -e "{{ default_channel }}\s\+{{ bundle_channel }}" | awk '{ print $NF }' - register: bundle_image_raw - -- name: Set bundle image fact - ansible.builtin.set_fact: - bundle_image: "{{ bundle_image_raw.stdout }}" - -- name: Fail if bundle_image is empty - ansible.builtin.fail: - msg: "Failed to find bundle image: {{ bundle_image_raw }}" - when: > - (bundle_image is not defined) or (bundle_image | length == 0) - -# all_images will be a list as follows: -# [ "registry.redhat.io/rh-sso-7/sso75-openshift-rhel8@sha256:d5829e880db4b82a50a4962d61ea148522a93644174931b256d7ad866eadcf40", -# "registry.redhat.io/openshift-gitops-1/gitops-rhel8@sha256:5ff915a399c1cc12d4f932652b410bf7399850934833e755267bdd409f4ce11b", -# "registry.redhat.io/openshift-gitops-1/argocd-rhel8@sha256:81e0574159c6aaabe7125d27782a5e6e5e72383a4a0ba76b44d465f3a3098759", -# "registry.redhat.io/rhel8/redis-6@sha256:53598a6effeb90e4f1b005b2521beffd2fa2b0c52d0e7f2347ee2abd2577cab3", -# "registry.redhat.io/openshift-gitops-1/gitops-rhel8-operator@sha256:efbfb010f24894f715a50832a4b3d2cdc221f283cbbdca05e388850586e9d792", -# "registry.redhat.io/openshift4/ose-haproxy-router@sha256:edf7ce748b703e195220b7bd7b42fa2caa4cdfd96840445e096036a0d85f1ff2", -# "registry.redhat.io/openshift-gitops-1/kam-delivery-rhel8@sha256:10c5a1b6a0858a812117e6fb2b28d37617d9eb83da5e4fb647059ff740a14461", -# "registry.redhat.io/openshift-gitops-1/dex-rhel8@sha256:6a3eaee6a4f8cb9a35363bf4c7f83a7fa2042ae62bdaa700ecd0893dd52276f5", -# "registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-gitops-operator-bundle@sha256:e463314596098a4e774e0dda..." ] -- name: Set all images fact (related images + operator bundles) - ansible.builtin.set_fact: - all_images: "{{ all_images + related_images + [bundle_image] }}" diff --git a/ansible/roles/iib_ci/tasks/install-iib-in-cluster.yml b/ansible/roles/iib_ci/tasks/install-iib-in-cluster.yml deleted file mode 100644 index 76a649b2..00000000 --- a/ansible/roles/iib_ci/tasks/install-iib-in-cluster.yml +++ /dev/null @@ -1,56 +0,0 @@ -- name: Set IIB local folder fact - ansible.builtin.set_fact: - iib_local_folder: "/tmp/manifest-{{ item.value['iib'] }}" - -- name: Remove manifest folder "{{ iib_local_folder }}" - ansible.builtin.file: - path: "{{ iib_local_folder }}" - state: absent - -- name: Create manifest folder "{{ iib_local_folder }}" - ansible.builtin.file: - path: "{{ iib_local_folder }}" - state: directory - mode: "0755" - -# This generates files in /tmp/manifest-IIB: -# - mapping.txt -# - catalogSource.yaml -# - imageContentSourcePolicy.yaml -- name: Mirror catalog manifests only to "{{ iib_local_folder }}" - ansible.builtin.shell: | - oc adm catalog mirror --insecure --manifests-only --to-manifests=. \ - "{{ item.value['iib_image'] }}" "{{ rh_internal_registry }}/rh-osbs" > catalog.log 2>&1 - args: - chdir: "{{ iib_local_folder }}" - -- name: Mirror IIB to "{{ mirror_iib }}" - ansible.builtin.shell: | - oc image mirror -a "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" \ - "{{ item.value['iib_image'] }}={{ mirror_iib }}" --insecure --keep-manifest-list 2>&1 - args: - chdir: "{{ iib_local_folder }}" - register: oc_mirror_result - retries: 10 - delay: 5 - until: oc_mirror_result is not failed - -- name: Template mirrored catalogsource - ansible.builtin.template: - src: ./templates/catalogSource.yaml.j2 - dest: "{{ iib_local_folder }}/mirrored-catalogsource.yaml" - mode: "0644" - -- name: Apply mirrored catalogsource - ansible.builtin.shell: | - oc apply -f "{{ iib_local_folder }}/mirrored-catalogsource.yaml" - -- name: Wait for catalogsource to show up - ansible.builtin.shell: | - oc get -n "{{ internal_registry_ns }}" packagemanifests -l "catalog=iib-{{ item.value['iib'] }}" --field-selector "metadata.name={{ item.key }}" \ - -o jsonpath='{.items[0].status.defaultChannel}' - register: oc_catalogsource_result - retries: 30 - delay: 10 - until: oc_catalogsource_result is not failed - changed_when: false diff --git a/ansible/roles/iib_ci/tasks/main.yml b/ansible/roles/iib_ci/tasks/main.yml deleted file mode 100644 index 4e8df11f..00000000 --- a/ansible/roles/iib_ci/tasks/main.yml +++ /dev/null @@ -1,76 +0,0 @@ -- name: Check for pre-requisite binaries presence - ansible.builtin.shell: | - which "{{ item }}" - with_items: - - skopeo - - oc - - podman - -- name: Check that INDEX_IMAGES env variable is set - ansible.builtin.fail: - msg: "INDEX_IMAGES: '{{ iib_images }}' is not set" - failed_when: - (iib_images is not defined or iib_images | length == 0) - -- name: Get cluster version - # E.g. 4.13.0-rc.6 or 4.12.16 - ansible.builtin.shell: | - oc get openshiftcontrollermanager/cluster -o yaml -o jsonpath='{.status.version}' - register: oc_version_raw - retries: 10 - delay: 10 - until: oc_version_raw is not failed - changed_when: false - -- name: Is OCP pre OCP 4.13? (aka registry supports v2 manifests) - ansible.builtin.set_fact: - ocp_413: "{{ oc_version_raw.stdout is version('4.13', '>=') }}" - -- name: Fail if OCP < 4.13 as we do not support it for IIB testing any longer - ansible.builtin.fail: - msg: "OCP versions < 4.13 are not support for IIB loading" - when: not ocp_413 - -- name: Set images array - ansible.builtin.set_fact: - iib_image_list: "{{ iib_images.split(',') }}" - -- name: Set operator array - ansible.builtin.set_fact: - operator_list: "{{ operator.split(',') }}" - -# Creates a dict like: -# "advanced-cluster-management": { -# "iib": "713808", -# "iib_image": "registry-proxy.engineering.redhat.com/rh-osbs/iib:713808" -# }, -# "multicluster-engine": { -# "iib": "713809", -# "iib_image": "registry-proxy.engineering.redhat.com/rh-osbs/iib:713809" -# } -- name: Set IIB dict - ansible.builtin.set_fact: - iib_dict: "{{ iib_dict | default({}) | combine({item.0: {'iib_image': item.1, 'iib': item.1.split(':')[-1]}}) }}" - with_together: - - "{{ operator_list }}" - - "{{ iib_image_list }}" - -- name: Working with the following IIB data - ansible.builtin.debug: - msg: "{{ iib_dict }}" - -- name: Set up internal registry (OCP >= 4.13) - ansible.builtin.include_tasks: setup-internal-registry.yml - -- name: Install new IIB in cluster - ansible.builtin.include_tasks: install-iib-in-cluster.yml - with_items: "{{ iib_dict | dict2items }}" - -- name: Mirror all related images - ansible.builtin.include_tasks: mirror-related-images.yml - with_items: "{{ iib_dict | dict2items }}" - -- name: Remove pullsecrets tempfolder - ansible.builtin.file: - path: "{{ pull_secrets_tempfolder.path }}" - state: absent diff --git a/ansible/roles/iib_ci/tasks/mirror-related-images.yml b/ansible/roles/iib_ci/tasks/mirror-related-images.yml deleted file mode 100644 index 74a0bc3b..00000000 --- a/ansible/roles/iib_ci/tasks/mirror-related-images.yml +++ /dev/null @@ -1,217 +0,0 @@ -# We redefine this var so it is easier to run this task independently -- name: Set IIB local folder fact - ansible.builtin.set_fact: - iib_local_folder: "/tmp/manifest-{{ item.value['iib'] }}" - -- name: Set all images to empty list - ansible.builtin.set_fact: - all_images: [] - -- name: Fetch operator images tasks - ansible.builtin.include_tasks: fetch-operator-images.yml - -- name: Print all_images - ansible.builtin.debug: - msg: "{{ all_images }}" - -# A mapping.txt file will have lines like the following. Note how the image to the right of '=' -# does have a shortened hash! : -# registry.redhat.io/openshift-gitops-1/gitops-rhel8@sha256:5ff...=registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-gitops-rhel8:8256cca6 -# registry.redhat.io/openshift4/ose-haproxy-router@sha256:edf..=registry-proxy.engineering.redhat.com/rh-osbs/openshift4-ose-haproxy-router:a636cbea -# -# Now what we are doing here is the following: -# 1. For every image we get from the bundle (contained in all_images var) we check if it exists. If it does great, skip to the next image -# 2. If the image was not found above, we take the corresponding URL on the right hand side of the '=' sign in mapping.txt -# except that we drop the hash that exists on the right hand-side and just use the one we were given with the image. -# If the image is found, great. If not we need to error out because we have no idea where we can fetch it from -- name: Find out which images really exist by consulting mapping.txt - ansible.builtin.shell: | - set -o pipefail - left_sha=$(echo "{{ image }}" | sed -e 's/^.*@//') - right=$(grep "{{ image }}" "{{ iib_local_folder }}/mapping.txt" | cut -f2 -d=) - right_base=$(echo $right | sed -e 's/:.*$//' -e 's/@.*$//') - right_log=$(echo "${right_base}@${left_sha}" | sed -e 's/\//-/g') - left_out=$(skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"{{ image }}" 2>&1) - left_ret=$? - if [ $left_ret -eq 0 ]; then - echo "{{ image }}" - else - echo "${left_out}" > /tmp/skopeo-"{{ image | regex_replace('/', '-') }}".log - right_out=$(skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"${right_base}@${left_sha}" 2>&1) - right_ret=$? - if [ $right_ret -eq 0 ]; then - echo "${right_base}@${left_sha}" - else # both left_ret and right_ret were != 0 - echo "${right_out}" > "/tmp/skopeo-${right_log}.log" - echo "ERROR: both {{ image }} and echo ${right_base}@${left_sha} could not be found" - echo "Printing both outputs:" - echo "Left out: ${left_out}" - echo "Right out: ${right_out}" - exit 1 - fi - fi - register: all_existing_images - with_items: "{{ all_images }}" - loop_control: - loop_var: image - -# The dictionary below will be in the following form: -# { -# "registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-gitops-operator-bundle@sha256:e463314596098a4e774e0ddaed0009bfdad4d79b664e28fef219c796679ee6a0": { -# "source": "registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-gitops-operator-bundle@sha256:e463314596098a4e774e0ddaed0009bfdad4d79b664e28fef219c796679ee6a0" -# }, -# "registry.redhat.io/openshift-gitops-1/argocd-rhel8@sha256:81e0574159c6aaabe7125d27782a5e6e5e72383a4a0ba76b44d465f3a3098759": { -# "source": "registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-argocd-rhel8@sha256:81e0574159c6aaabe7125d27782a5e6e5e72383a4a0ba76b44d465f3a3098759" -# }, -# "registry.redhat.io/openshift-gitops-1/dex-rhel8@sha256:6a3eaee6a4f8cb9a35363bf4c7f83a7fa2042ae62bdaa700ecd0893dd52276f5": { -# "source": "registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-dex-rhel8@sha256:6a3eaee6a4f8cb9a35363bf4c7f83a7fa2042ae62bdaa700ecd0893dd52276f5" -# }, -# "registry.redhat.io/openshift-gitops-1/gitops-rhel8-operator@sha256:efbfb010f24894f715a50832a4b3d2cdc221f283cbbdca05e388850586e9d792": { -# "source": "registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-gitops-rhel8-operator@sha256:efbfb010f24894f715a50832a4b3d2cdc221f283cbbdca05e388850586e9d792" -# }, -# "registry.redhat.io/openshift-gitops-1/gitops-rhel8@sha256:5ff915a399c1cc12d4f932652b410bf7399850934833e755267bdd409f4ce11b": { -# "source": "registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-gitops-rhel8@sha256:5ff915a399c1cc12d4f932652b410bf7399850934833e755267bdd409f4ce11b" -# }, -# "registry.redhat.io/openshift-gitops-1/kam-delivery-rhel8@sha256:10c5a1b6a0858a812117e6fb2b28d37617d9eb83da5e4fb647059ff740a14461": { -# "source": "registry-proxy.engineering.redhat.com/rh-osbs/openshift-gitops-1-kam-delivery-rhel8@sha256:10c5a1b6a0858a812117e6fb2b28d37617d9eb83da5e4fb647059ff740a14461" -# }, -# "registry.redhat.io/openshift4/ose-haproxy-router@sha256:edf7ce748b703e195220b7bd7b42fa2caa4cdfd96840445e096036a0d85f1ff2": { -# "source": "registry.redhat.io/openshift4/ose-haproxy-router@sha256:edf7ce748b703e195220b7bd7b42fa2caa4cdfd96840445e096036a0d85f1ff2" -# }, -# "registry.redhat.io/rh-sso-7/sso75-openshift-rhel8@sha256:d5829e880db4b82a50a4962d61ea148522a93644174931b256d7ad866eadcf40": { -# "source": "registry.redhat.io/rh-sso-7/sso75-openshift-rhel8@sha256:d5829e880db4b82a50a4962d61ea148522a93644174931b256d7ad866eadcf40" -# }, -# "registry.redhat.io/rhel8/redis-6@sha256:53598a6effeb90e4f1b005b2521beffd2fa2b0c52d0e7f2347ee2abd2577cab3": { -# "source": "registry.redhat.io/rhel8/redis-6@sha256:53598a6effeb90e4f1b005b2521beffd2fa2b0c52d0e7f2347ee2abd2577cab3" -# } -# } -- name: Create dict with full image name+sha -> url where we will fetch it from - ansible.builtin.set_fact: - image_urls: "{{ image_urls | default({}) | combine({item: {'source': all_existing_images.results[counter].stdout, - 'source_nosha': all_existing_images.results[counter].stdout | regex_replace('@.*$', '')}}, recursive=true) }}" - loop: "{{ all_images }}" - loop_control: - index_var: counter - -- name: Create dict with full image name+sha -> mirror destination (OCP >= 4.13) - ansible.builtin.set_fact: - image_urls: "{{ image_urls | default({}) | combine({item: - {'mirrordest': mirror_dest + item | basename, - 'mirrordest_nosha': (mirror_dest + item | basename) | regex_replace('@.*$', ''), - 'mirrordest_tag': 'tag-' + item | basename | regex_replace('^.*@sha256:', '')}}, recursive=true) }}" - loop: "{{ all_images }}" - -- name: Create dict with full image name+sha -> image key without sha - ansible.builtin.set_fact: - image_urls: "{{ image_urls | default({}) | combine({item: {'image_nosha': item | regex_replace('@.*$', '')}}, recursive=true) }}" - loop: "{{ all_images }}" - -# At this point the dictionary looks as follows: -# "registry.redhat.io/rhel8/redis-6@sha256:53598a6effeb90e4f1b005b2521beffd2fa2b0c52d0e7f2347ee2abd2577cab3": { -# "mirrordest": "default-route-openshift-image-registry.apps.mcg-hub.blueprints.rhecoeng.com/openshift-marketplace/redis-6@sha256:535... -# "mirrordest_nosha": "default-route-openshift-image-registry.apps.mcg-hub.blueprints.rhecoeng.com/openshift-marketplace/redis-6", -# "source": "registry.redhat.io/rhel8/redis-6@sha256:53598a6effeb90e4f1b005b2521beffd2fa2b0c52d0e7f2347ee2abd2577cab3", -# "source_nosha": "registry.redhat.io/rhel8/redis-6" -# } -- name: Print dict with full images - ansible.builtin.debug: - msg: "{{ image_urls }}" - -# OCP 4.13 uses the new fangled "ImageDigestMirrorSet" -- name: Template out imageMirror.yaml (OCP >= 4.13) - ansible.builtin.template: - src: ./templates/imageDigestMirror.yaml.j2 - dest: "{{ iib_local_folder }}/imageMirror.yaml" - mode: "0644" - -- name: Template out mirror.map - ansible.builtin.template: - src: ./templates/mirror.map.j2 - dest: "{{ iib_local_folder }}/mirror.map" - mode: "0644" - -# NOTE(bandini): mirror.map *must* have a tag (we use the IIB number) on the image on the right side -# otherwise, the image will be uplaoded and will exist in S3 but it won't exist in the registry's catalog!! -- name: Mirror all the needed images - ansible.builtin.shell: | - set -o pipefail - oc image mirror -a "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" -f mirror.map --insecure --keep-manifest-list 2>&1 | tee -a image-mirror.log - args: - chdir: "{{ iib_local_folder }}" - retries: 5 - delay: 2 - register: oc_mirror - until: oc_mirror is not failed - -- name: Fetch MCP observedGeneration worker - ansible.builtin.shell: - oc get mcp/worker -o jsonpath='{.status.observedGeneration}' - register: worker_observed_generation_raw - -- name: Fetch MCP machineCount worker - ansible.builtin.shell: - oc get mcp/worker -o jsonpath='{.status.machineCount}' - register: worker_machinecount_raw - -- name: Fetch MCP observedGeneration master - ansible.builtin.shell: - oc get mcp/master -o jsonpath='{.status.observedGeneration}' - register: master_observed_generation_raw - -- name: Fetch MCP machineCount master - ansible.builtin.shell: - oc get mcp/master -o jsonpath='{.status.machineCount}' - register: master_machinecount_raw - -- name: Will the imageMirror trigger any changes - ansible.builtin.command: - oc diff -f "{{ iib_local_folder }}/imageMirror.yaml" - failed_when: false - register: oc_mirror_diff - -# We only run this piece if there is an actual change in the mirror digest for images -# cannot use 'is failed' as that is always false when setting failed_when: false above -- name: Apply imageMirror and wait for MCP to complete - when: oc_mirror_diff.rc != 0 - block: - - name: Apply imageMirror - ansible.builtin.command: - oc apply -f "{{ iib_local_folder }}/imageMirror.yaml" - - # NOTE(bandini): The reason to not fail on these two observedGeneration waiting - # tasks, is to make this idempotent: If the 'oc apply' above does *not* trigger - # any changes, the observed generation tasks will just timeout. And then we still - # wait to make sure that the readyworker count is correct. - - name: Wait for MCP new observedGeneration worker - ansible.builtin.shell: - oc get mcp/worker -o jsonpath='{.status.observedGeneration}' - register: worker_current_observed_generation_raw - retries: 10 - delay: 20 - until: worker_current_observed_generation_raw.stdout != worker_observed_generation_raw.stdout - failed_when: false - - - name: Wait for MCP new observedGeneration master - ansible.builtin.shell: - oc get mcp/master -o jsonpath='{.status.observedGeneration}' - register: master_current_observed_generation_raw - retries: 10 - delay: 20 - until: master_current_observed_generation_raw.stdout != master_observed_generation_raw.stdout - failed_when: false - - - name: Wait for MCP readyMachineCount to be the same as before applying the digest (worker) - ansible.builtin.shell: - oc get mcp/worker -o jsonpath='{.status.readyMachineCount}' - register: worker_current_ready_machinecount_raw - retries: 30 - delay: 10 - until: worker_current_ready_machinecount_raw.stdout == worker_machinecount_raw.stdout - - - name: Wait for MCP readyMachineCount to be the same as before applying the digest (master) - ansible.builtin.shell: - oc get mcp/master -o jsonpath='{.status.readyMachineCount}' - register: master_current_ready_machinecount_raw - retries: 30 - delay: 10 - until: master_current_ready_machinecount_raw.stdout == master_machinecount_raw.stdout diff --git a/ansible/roles/iib_ci/tasks/setup-internal-registry.yml b/ansible/roles/iib_ci/tasks/setup-internal-registry.yml deleted file mode 100644 index e45def74..00000000 --- a/ansible/roles/iib_ci/tasks/setup-internal-registry.yml +++ /dev/null @@ -1,108 +0,0 @@ -- name: Check KUBEADMINPASS is set - ansible.builtin.fail: - msg: "KUBEADMINPASS: '{{ kubeadminpass }}' is not set" - failed_when: kubeadminpass is not defined or kubeadminpass | length == 0 - -- name: Get kubeadmin api endpoint - ansible.builtin.command: - oc whoami --show-server=true - register: kubeadminapi_raw - -- name: Set kubeadminapi fact - ansible.builtin.set_fact: - kubeadminapi: "{{ kubeadminapi_raw.stdout }}" - -- name: Login via kubeadmin - ansible.builtin.command: | - oc login -u kubeadmin -p "{{ kubeadminpass }}" "{{ kubeadminapi }}" --insecure-skip-tls-verify=true - -- name: Get kubeadmin token - ansible.builtin.command: | - oc whoami -t - register: oc_whoami_raw - -- name: Set kubeadmin token - ansible.builtin.set_fact: - kubeadmin_token: "{{ oc_whoami_raw.stdout }}" - -- name: Expose internal registry route - ansible.builtin.shell: | - oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge - -- name: Fetch internal registry route value - ansible.builtin.command: - oc registry info --public=true - register: registry_route_raw - retries: 20 - delay: 20 - until: - - registry_route_raw is not failed - - registry_route_raw.stdout | length > 0 - -- name: Set route fact - ansible.builtin.set_fact: - registry_route: "{{ registry_route_raw.stdout }}" - -- name: Set registry allowedRegistries - ansible.builtin.shell: > - oc patch image.config.openshift.io/cluster --patch "{\"spec\":{\"registrySources\":{\"allowedRegistries\":[ \"registry.stage.redhat.io\", \"registry.access.redhat.com\", \"registry.connect.redhat.com\", \"ghcr.io\", \"gcr.io\", \"quay.io\", \"registry.redhat.io\", \"docker.io\", - \"registry-proxy.engineering.redhat.com\", \"image-registry.openshift-image-registry.svc:5000\", \"{{ registry_route }}\"]}}}" --type=merge - -- name: Set registry insecureRegistries - ansible.builtin.shell: > - oc patch image.config.openshift.io/cluster --patch "{\"spec\":{\"registrySources\":{\"insecureRegistries\":[ \"registry-proxy.engineering.redhat.com\", - \"image-registry.openshift-image-registry.svc:5000\", \"{{ registry_route }}\"]}}}" --type=merge - -- name: Get current cluster pull secrets - ansible.builtin.command: - oc extract secret/pull-secret -n openshift-config --to=- - register: pull_secrets_raw - -- name: Add local registry to pull secrets and set auth fact - ansible.builtin.set_fact: - pull_secrets_new: "{{ pull_secrets_raw.stdout | from_json }}" - internal_registry_auth: "{{ ('kubeadmin:' + kubeadmin_token) | b64encode }}" - -- name: Add local registry to pull secrets - ansible.builtin.set_fact: - pull_secrets: "{{ pull_secrets_new | combine({'auths': {registry_route: {'email': internal_registry_email, 'auth': internal_registry_auth}}}, recursive=true) }}" - -- name: Get a tempfile for the pull secrets - ansible.builtin.tempfile: - state: directory - register: pull_secrets_tempfolder - -- name: Store pull secrets in tempfile - ansible.builtin.copy: - dest: "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" - content: "{{ pull_secrets | to_nice_json }}" - mode: "0644" - -- name: Update pull-secret in the cluster - ansible.builtin.shell: | - oc set data secret/pull-secret -n openshift-config --from-file="{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" - -- name: Before proceeding here we need to make sure that the MCPs have all settled - ansible.builtin.shell: | - if [ $(oc get mcp/master -o jsonpath='{.status.readyMachineCount}') != $(oc get mcp/master -o jsonpath='{.status.machineCount}') ]; then - exit 1 - fi - if [ $(oc get mcp/worker -o jsonpath='{.status.readyMachineCount}') != $(oc get mcp/worker -o jsonpath='{.status.machineCount}') ]; then - exit 1 - fi - retries: 30 - delay: 20 - register: mcp_ready - until: mcp_ready is not failed - -- name: Login the internal registry with podman - ansible.builtin.command: - podman login --tls-verify=false --username unused --password "{{ kubeadmin_token }}" "{{ registry_route }}" - -- name: Set Mirror URL fact for internal mirror IIB - ansible.builtin.set_fact: - mirror_iib: "{{ registry_route }}/{{ internal_registry_ns }}/iib" - -- name: Set Mirror URL fact for internal mirror - ansible.builtin.set_fact: - mirror_dest: "{{ registry_route }}/{{ internal_registry_ns }}/" diff --git a/ansible/roles/iib_ci/templates/catalogSource.yaml.j2 b/ansible/roles/iib_ci/templates/catalogSource.yaml.j2 deleted file mode 100644 index e7498892..00000000 --- a/ansible/roles/iib_ci/templates/catalogSource.yaml.j2 +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: CatalogSource -metadata: - name: iib-{{ item.value['iib'] }} - namespace: {{ internal_registry_ns }} -spec: - image: {{ mirror_iib }}:{{ item.value['iib'] }} - sourceType: grpc - displayName: IIB {{ item.value['iib'] }} diff --git a/ansible/roles/iib_ci/templates/htpasswd-oauth.yaml b/ansible/roles/iib_ci/templates/htpasswd-oauth.yaml deleted file mode 100644 index 8fc41821..00000000 --- a/ansible/roles/iib_ci/templates/htpasswd-oauth.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: config.openshift.io/v1 -kind: OAuth -metadata: - name: cluster -spec: - identityProviders: - - name: my_htpasswd_provider - mappingMethod: claim - type: HTPasswd - challenge: true - login: true - htpasswd: - fileData: - name: htpass-secret diff --git a/ansible/roles/iib_ci/templates/imageContentSourcePolicy.yaml.j2 b/ansible/roles/iib_ci/templates/imageContentSourcePolicy.yaml.j2 deleted file mode 100644 index d0f417ec..00000000 --- a/ansible/roles/iib_ci/templates/imageContentSourcePolicy.yaml.j2 +++ /dev/null @@ -1,19 +0,0 @@ ---- -apiVersion: operator.openshift.io/v1alpha1 -kind: ImageContentSourcePolicy -metadata: - labels: - operators.openshift.org/catalog: "true" - name: iib-{{ iib }} -spec: - repositoryDigestMirrors: -{% for item in image_urls.values() %} - - mirrors: - - {{ item.mirrordest_nosha }} - source: {{ item.source_nosha }} - mirrorSourcePolicy: NeverContactSource - - mirrors: - - {{ item.mirrordest_nosha }} - source: {{ item.image_nosha }} - mirrorSourcePolicy: NeverContactSource -{% endfor %} diff --git a/ansible/roles/iib_ci/templates/imageDigestMirror.yaml.j2 b/ansible/roles/iib_ci/templates/imageDigestMirror.yaml.j2 deleted file mode 100644 index 08a24735..00000000 --- a/ansible/roles/iib_ci/templates/imageDigestMirror.yaml.j2 +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: config.openshift.io/v1 -kind: ImageDigestMirrorSet -metadata: - labels: - operators.openshift.org/catalog: "true" - name: iib-{{ item.value['iib'] }} -spec: - imageDigestMirrors: -{% for data in image_urls.values() %} - - mirrors: - - {{ data.mirrordest_nosha }} - source: {{ data.source_nosha }} - mirrorSourcePolicy: AllowContactingSource - - mirrors: - - {{ data.mirrordest_nosha }} - source: {{ data.image_nosha }} - mirrorSourcePolicy: AllowContactingSource -{% endfor %} diff --git a/ansible/roles/iib_ci/templates/mirror.map.j2 b/ansible/roles/iib_ci/templates/mirror.map.j2 deleted file mode 100644 index ecef721c..00000000 --- a/ansible/roles/iib_ci/templates/mirror.map.j2 +++ /dev/null @@ -1,3 +0,0 @@ -{% for item in image_urls.values() %} -{{ item.source }}={{ item.mirrordest_nosha }}:{{ item.mirrordest_tag }} -{% endfor %} diff --git a/ansible/roles/iib_ci/vars/main.yml b/ansible/roles/iib_ci/vars/main.yml deleted file mode 100644 index 56894088..00000000 --- a/ansible/roles/iib_ci/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for iib_ci diff --git a/ansible/roles/k8s_secret_utils/defaults/main.yml b/ansible/roles/k8s_secret_utils/defaults/main.yml deleted file mode 100644 index 7ebda207..00000000 --- a/ansible/roles/k8s_secret_utils/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -secrets_ns: 'validated-patterns-secrets' diff --git a/ansible/roles/k8s_secret_utils/tasks/inject_k8s_secret.yml b/ansible/roles/k8s_secret_utils/tasks/inject_k8s_secret.yml deleted file mode 100644 index 283fb6a2..00000000 --- a/ansible/roles/k8s_secret_utils/tasks/inject_k8s_secret.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -- name: Check for secrets namespace - no_log: false - kubernetes.core.k8s_info: - kind: Namespace - name: "{{ item['metadata']['namespace'] }}" - register: secrets_ns_rc - until: secrets_ns_rc.resources | length > 0 - retries: 20 - delay: 45 - -- name: Inject k8s secret - no_log: '{{ override_no_log | default(True) }}' - kubernetes.core.k8s: - definition: '{{ item }}' diff --git a/ansible/roles/k8s_secret_utils/tasks/inject_k8s_secrets.yml b/ansible/roles/k8s_secret_utils/tasks/inject_k8s_secrets.yml deleted file mode 100644 index a2299734..00000000 --- a/ansible/roles/k8s_secret_utils/tasks/inject_k8s_secrets.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: Inject secrets - no_log: '{{ override_no_log | default(True) }}' - ansible.builtin.include_tasks: inject_k8s_secret.yml - loop: '{{ kubernetes_secret_objects }}' diff --git a/ansible/roles/k8s_secret_utils/tasks/main.yml b/ansible/roles/k8s_secret_utils/tasks/main.yml deleted file mode 100644 index d72de7ae..00000000 --- a/ansible/roles/k8s_secret_utils/tasks/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: Parse and extract k8s secrets from values-secret file - ansible.builtin.include_tasks: parse_secrets.yml - -- name: Inject k8s secrets - ansible.builtin.include_tasks: inject_k8s_secrets.yml diff --git a/ansible/roles/k8s_secret_utils/tasks/parse_secrets.yml b/ansible/roles/k8s_secret_utils/tasks/parse_secrets.yml deleted file mode 100644 index b1755cc2..00000000 --- a/ansible/roles/k8s_secret_utils/tasks/parse_secrets.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Parse secrets data - # no_log: '{{ override_no_log | default(true) }}' - parse_secrets_info: - values_secrets_plaintext: "{{ values_secrets_data }}" - secrets_backing_store: "{{ secrets_backing_store }}" - register: secrets_results - -- name: Return kubernetes objects - no_log: '{{ override_no_log | default(true) }}' - ansible.builtin.set_fact: - kubernetes_secret_objects: "{{ secrets_results['kubernetes_secret_objects'] }}" diff --git a/ansible/roles/vault_utils/README.md b/ansible/roles/vault_utils/README.md deleted file mode 100644 index ba26c702..00000000 --- a/ansible/roles/vault_utils/README.md +++ /dev/null @@ -1,241 +0,0 @@ -# Role Name - -Bunch of utilities to manage the vault inside k8s imperatively - -## Requirements - -ansible-galaxy collection install kubernetes.core (formerly known as community.kubernetes) - -## Role Variables - -Defaults as to where the values-secret.yaml file is and the two ways to connect to a kubernetes cluster -(KUBERCONFIG and ~/.kube/config respectively): - -```yaml -values_secret: "{{ lookup('env', 'HOME') }}/values-secret.yaml" -kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" -kubeconfig_backup: "{{ lookup('env', 'HOME') }}/.kube/config" -``` - -Default values for vault configuration: - -```yaml -vault_ns: "vault" -vault_pod: "vault-0" -vault_hub: "hub" -vault_hub_kubernetes_host: https://$KUBERNETES_PORT_443_TCP_ADDR:443 -# Needs extra escaping due to how it gets injected via shell in the vault -vault_hub_capabilities: '[\\\"read\\\"]' -vault_base_path: "secret" -vault_path: "{{ vault_base_path }}/{{ vault_hub }}" -vault_hub_ttl: "15m" -vault_pki_max_lease_ttl: "8760h" -external_secrets_ns: golang-external-secrets -external_secrets_sa: golang-external-secrets -unseal_secret: "vaultkeys" -unseal_namespace: "imperative" -``` - -## Dependencies - -This relies on [kubernetes.core](https://docs.ansible.com/ansible/latest/collections/kubernetes/core/k8s_module.html) - -## Vault out of the box configuration - -This role configures four secret paths in vault: - -1. `secret/global` - Any secret under this path is accessible in read-only only to all clusters known to ACM (hub and spokes) -2. `secret/hub` - Any secret under this path is accessible in read-only only to the ACM hub cluster -3. `secret/` - Any secret under this path is accessible in read-only only to the spoke cluster -4. `secret/pushsecrets` - Any secret here can be accessed in read and write mode to all clusters known to ACM. This area can - be used with ESO's `PushSecrets` so you can push an existing secret from one namespace, to the vault under this path and - then it can be retrieved by an `ExternalSecret` either in a different namespace *or* from an entirely different cluster. - -## Values secret file format - -Currently this role supports two formats: version 1.0 (which is the assumed -default when not specified) and version 2.0. The latter is more fatureful and -supports generating secrets directly into the vault and also prompting the user -for a secret. - -By default, the first file that will looked up is -`~/.config/hybrid-cloud-patterns/values-secret-.yaml`, then -`~/.config/validated-patterns/values-secret-.yaml`, -`~/values-secret-.yaml` and should that not exist it will look for -`~/values-secret.yaml`. -The paths can be overridden by setting the environment variable `VALUES_SECRET` to the path of the -secret file. - -The values secret YAML files can be encrypted with `ansible-vault`. If the role detects they are encrypted, the password to -decrypt them will be prompted when needed. - -### Version 2.0 - -Here is a version 2.0 example file (specifying `version: 2.0` is mandatory in this case): - -```yaml -# NEVER COMMIT THESE VALUES TO GIT (unless your file only uses generated -# passwords or only points to files) - -# Needed to specify the new format (missing version means old version: 1.0 by default) -version: 2.0 - -backingStore: vault # 'vault' is the default when omitted - -# These are the vault policies to be created in the vault -# these are used when we let the vault generate the passwords -# by setting the 'onMissingValue' attribute to 'generate' -# See https://developer.hashicorp.com/vault/docs/concepts/password-policies -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#$%^&*" min-chars = 1 } - -# This is the mandatory top-level secrets entry -secrets: - # This will create the following keys + attributes: - # - secret/region-one/config-demo: - # secret: ...... - # secretprompt: ...... - # secretprompt2: ...... - # secretfile: ...... - # ca_crt_b64: ...... - # - secret/snowflake.blueprints.rhecoeng.com: - # secret: ...... - # secretprompt: ...... - # secretprompt2: ...... - # secretfile: ...... - # ca_crt_b64: ...... - - name: config-demo - # This is the default and passes the -mount=secret option to the vault commands - vaultMount: secret - # These represent the paths inside the vault maint - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate # One of: error,generate,prompt (generate is only valid for normal secrets) - # This override attribute is false by default. The attribute is only valid with 'generate'. If the secret already exists in the - # vault it won't be changed unless override is set to true - override: true - vaultPolicy: basicPolicy - - name: secretprompt - value: null - onMissingValue: prompt # when prompting for something you need to set either value: null or path: null as - # we need to know if it is a secret plaintext or a file path - description: "Please specify the password for application ABC" - - name: secretprompt2 - value: defaultvalue - onMissingValue: prompt - description: "Please specify the API key for XYZ" - - name: secretprompt3 - onMissingValue: generate - vaultPolicy: validatedPatternDefaultPolicy # This is an always-existing hard-coded policy - - name: secretfile - path: /tmp/ca.crt - onMissingValue: prompt - description: "Insert path to Certificate Authority" - - name: ca_crt - path: /tmp/ca.crt - onMissingValue: error # One of error, prompt (for path). generate makes no sense for file - - name: ca_crt_b64 - path: /tmp/ca.crt - base64: true # defaults to false - onMissingValue: prompt # One of error, prompt (for path). generate makes no sense for file - - - name: config-demo2 - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: ca_crt2 - path: /tmp/ca.crt # this will be the default shown when prompted - description: "Specify the path for ca_crt2" - onMissingValue: prompt # One of error, prompt (for path). generate makes no sense for file - - name: ca_crt - path: /tmp/ca.crt - onMissingValue: error # One of error, prompt (for path). generate makes no sense for file - - # The following will read the ini-file at ~/.aws/credentials and place the ini_key "[default]/aws_access_key_id" - # in the aws_access_key_id_test vault attribute in the secret/hub/awsexample path - - name: awsexample - fields: - - name: aws_access_key_id_test - ini_file: ~/.aws/credentials - ini_section: default - ini_key: aws_access_key_id - - name: aws_secret_access_key_test - ini_file: ~/.aws/credentials - ini_key: aws_secret_access_key -``` - -### Version 1.0 - -Here is a well-commented example of a version 1.0 file: - -```yaml ---- -# By default when a top-level 'version: 1.0' is missing it is assumed to be '1.0' -# NEVER COMMIT THESE VALUES TO GIT - -secrets: - # These secrets will be pushed in the vault at secret/hub/test The vault will - # have secret/hub/test with secret1 and secret2 as keys with their associated - # values (secrets) - test: - secret1: foo - secret2: bar - - # This ends up as the s3Secret attribute to the path secret/hub/aws - aws: - s3Secret: test-secret - -# This will create the vault key secret/hub/testfoo which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files: - testfoo: ~/ca.crt -# These secrets will be pushed in the vault at secret/region1/test The vault will -# have secret/region1/test with secret1 and secret2 as keys with their associated -# values (secrets) -secrets.region1: - test: - secret1: foo1 - secret2: bar1 -# This will create the vault key secret/region2/testbar which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files.region2: - testbar: ~/ca.crt -``` - -Internals ---------- - -Here is the rough high-level algorithm used to unseal the vault: - -1. Check vault status. If vault is not initialized go to 2. If initialized go to 3. -2. Initialize vault and store unseal keys + login token inside a secret in k8s -3. Check vault status. If vault is unsealed go to 5. else to to 4. -4. Unseal the vault using the secrets read from the k8s secret -5. Configure the vault (should be idempotent) - -## License - -Apache - -## Author Information - -Michele Baldessari diff --git a/ansible/roles/vault_utils/defaults/main.yml b/ansible/roles/vault_utils/defaults/main.yml deleted file mode 100644 index 7759db48..00000000 --- a/ansible/roles/vault_utils/defaults/main.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -# defaults file for vault_utils -values_secret: "{{ lookup('env', 'HOME') }}/values-secret.yaml" -kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" -kubeconfig_backup: "{{ lookup('env', 'HOME') }}/.kube/config" -vault_ns: "vault" -vault_pod: "vault-0" -vault_hub: "hub" -vault_pvc: "data-vault-0" -vault_hub_kubernetes_host: https://$KUBERNETES_PORT_443_TCP_ADDR:443 -# Needs extra escaping due to how it gets injected via shell in the vault -vault_hub_capabilities: '[\\\"read\\\"]' -vault_base_path: "secret" -vault_path: "{{ vault_base_path }}/{{ vault_hub }}" -vault_hub_ttl: "15m" -vault_spoke_capabilities: '[\\\"read\\\"]' -vault_spoke_ttl: "15m" -vault_global_policy: global -vault_global_capabilities: '[\\\"read\\\"]' -vault_pushsecrets_policy: pushsecrets -vault_pushsecrets_capabilities: '[\\\"create\\\",\\\"read\\\",\\\"update\\\",\\\"delete\\\"]' -external_secrets_ns: golang-external-secrets -external_secrets_sa: golang-external-secrets -external_secrets_secret: golang-external-secrets -unseal_secret: "vaultkeys" -unseal_namespace: "imperative" diff --git a/ansible/roles/vault_utils/handlers/main.yml b/ansible/roles/vault_utils/handlers/main.yml deleted file mode 100644 index a983544d..00000000 --- a/ansible/roles/vault_utils/handlers/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# handlers file for vault_utils diff --git a/ansible/roles/vault_utils/meta/main.yml b/ansible/roles/vault_utils/meta/main.yml deleted file mode 100644 index c99eb3a9..00000000 --- a/ansible/roles/vault_utils/meta/main.yml +++ /dev/null @@ -1,31 +0,0 @@ -galaxy_info: - author: Validated Patterns Team https://github.com/hybrid-cloud-patterns/ - description: Utilities to manage vault in kubernetes (init, unseal, etc) - - issue_tracker_url: https://github.com/hybrid-cloud-patterns/common/issues - license: Apache-2.0 - min_ansible_version: "2.1" - - # If this a Container Enabled role, provide the minimum Ansible Container version. - # min_ansible_container_version: - - platforms: - - name: Fedora - versions: - - all - - name: Ubuntu - versions: - - all - - name: Debian - versions: - - all - - name: EL - versions: - - "8" - - "9" - - galaxy_tags: [] - -dependencies: [] - # List your role dependencies here, one per line. Be sure to remove the '[]' above, - # if you add dependencies to this list. diff --git a/ansible/roles/vault_utils/tasks/main.yml b/ansible/roles/vault_utils/tasks/main.yml deleted file mode 100644 index 1072e6b7..00000000 --- a/ansible/roles/vault_utils/tasks/main.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -- name: Run vault init tasks - ansible.builtin.import_tasks: vault_init.yaml - tags: vault_init - -- name: Unseal vault - ansible.builtin.import_tasks: vault_unseal.yaml - tags: vault_unseal - -- name: Vault secrets init - ansible.builtin.import_tasks: vault_secrets_init.yaml - tags: vault_secrets_init - -- name: Vault spoke backend init - ansible.builtin.import_tasks: vault_spokes_init.yaml - tags: vault_spokes_init - -- name: Load secrets - ansible.builtin.import_tasks: push_secrets.yaml - tags: push_secrets diff --git a/ansible/roles/vault_utils/tasks/push_parsed_secrets.yaml b/ansible/roles/vault_utils/tasks/push_parsed_secrets.yaml deleted file mode 100644 index cbca15e0..00000000 --- a/ansible/roles/vault_utils/tasks/push_parsed_secrets.yaml +++ /dev/null @@ -1,43 +0,0 @@ ---- -- name: "Do pre-checks for Vault" - ansible.builtin.include_role: - name: vault_utils - tasks_from: vault_status - -# Unfortunately we cannot loop vault_status and just check if the vault is unsealed -# https://github.com/ansible/proposals/issues/136 -# So here we keep running the 'vault status' command until sealed is set to false -- name: If the vault is still sealed we need to retry - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: vault status -format=json - register: vault_status_json - until: "'stdout' in vault_status_json and (not (vault_status_json.stdout | from_json)['sealed'] | bool)" - retries: 20 - delay: 45 - failed_when: "'stdout_lines' not in vault_status_json" - -# This step is not really needed when running make vault-init + load-secrets as -# everything is sequential -# It is needed when the vault is unsealed/configured inside the cluster and load-secrets -# gets run *while* the cronjob configures the vault. I.e. it might be half configured and return -# errors -- name: Make sure that the vault auth policy exists - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: - sh -c "vault list auth/{{ vault_hub }}/role | grep '{{ vault_hub }}-role'" - register: vault_role_cmd - until: - - vault_role_cmd.rc is defined - - vault_role_cmd.rc == 0 - retries: 20 - delay: 45 - changed_when: false - -- name: Load parsed secrets into cluster vault - vault_load_parsed_secrets: - vault_policies: "{{ vault_policies }}" - parsed_secrets: "{{ parsed_secrets }}" diff --git a/ansible/roles/vault_utils/tasks/push_secrets.yaml b/ansible/roles/vault_utils/tasks/push_secrets.yaml deleted file mode 100644 index 7954dc47..00000000 --- a/ansible/roles/vault_utils/tasks/push_secrets.yaml +++ /dev/null @@ -1,125 +0,0 @@ ---- -- name: Vault status check - ansible.builtin.include_tasks: vault_status.yaml - -# Unfortunately we cannot loop vault_status and just check if the vault is unsealed -# https://github.com/ansible/proposals/issues/136 -# So here we keep running the 'vault status' command until sealed is set to false -- name: If the vault is still sealed we need to retry - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: vault status -format=json - register: vault_status_json - until: "'stdout' in vault_status_json and (not (vault_status_json.stdout | from_json)['sealed'] | bool)" - retries: 20 - delay: 45 - failed_when: "'stdout_lines' not in vault_status_json" - -# This step is not really needed when running make vault-init + load-secrets as -# everything is sequential -# It is needed when the vault is unsealed/configured inside the cluster and load-secrets -# gets run *while* the cronjob configures the vault. I.e. it might be half configured and return -# errors -- name: Make sure that the vault auth policy exists - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: - sh -c "vault list auth/{{ vault_hub }}/role | grep '{{ vault_hub }}-role'" - register: vault_role_cmd - until: - - vault_role_cmd.rc is defined - - vault_role_cmd.rc == 0 - retries: 20 - delay: 45 - changed_when: false - -# Once V1 support is dropped we can remove the whole secret_template support -- name: Set secret_template fact - no_log: true - ansible.builtin.set_fact: - secret_template: "{{ pattern_dir }}/values-secret.yaml.template" - -- name: Is a VALUES_SECRET env variable set? - ansible.builtin.set_fact: - custom_env_values_secret: "{{ lookup('ansible.builtin.env', 'VALUES_SECRET') }}" - -- name: Check if VALUES_SECRET file exists - ansible.builtin.stat: - path: "{{ custom_env_values_secret }}" - register: custom_file_values_secret - when: custom_env_values_secret | default('') | length > 0 - -- name: Set values-secret yaml file to {{ custom_file_values_secret.stat.path }} - ansible.builtin.set_fact: - found_file: "{{ custom_file_values_secret.stat.path }}" - when: - - custom_env_values_secret | default('') | length > 0 - - custom_file_values_secret.stat.exists - -# FIXME(bandini): Eventually around end of 2023(?) we should drop -# ~/values-secret-{{ pattern_name }}.yaml and ~/values-secret.yaml -- name: Find first existing values-secret yaml file - ansible.builtin.set_fact: - found_file: "{{ lookup('ansible.builtin.first_found', findme) }}" - vars: - findme: - - "~/.config/hybrid-cloud-patterns/values-secret-{{ pattern_name }}.yaml" - - "~/.config/validated-patterns/values-secret-{{ pattern_name }}.yaml" - - "~/values-secret-{{ pattern_name }}.yaml" - - "~/values-secret.yaml" - - "{{ pattern_dir }}/values-secret.yaml.template" - when: custom_env_values_secret | default('') | length == 0 - -- name: Is found values secret file encrypted - no_log: true - ansible.builtin.shell: | - set -o pipefail - head -1 "{{ found_file }}" | grep -q \$ANSIBLE_VAULT - changed_when: false - register: encrypted - failed_when: (encrypted.rc not in [0, 1]) - -# When HOME is set we replace it with '~' in this debug message -# because when run from inside the container the HOME is /pattern-home -# which is confusing for users -- name: Is found values secret file encrypted - ansible.builtin.debug: - msg: "Using {{ (lookup('env', 'HOME') | length > 0) | ternary(found_file | regex_replace('^' + lookup('env', 'HOME'), '~'), found_file) }} to parse secrets" - -- name: Set encryption bool fact - no_log: true - ansible.builtin.set_fact: - is_encrypted: "{{ encrypted.rc == 0 | bool }}" - -- name: Get password for "{{ found_file }}" - ansible.builtin.pause: - prompt: "Input the password for {{ found_file }}" - echo: false - when: is_encrypted - register: vault_pass - -- name: Get decrypted content if {{ found_file }} was encrypted - no_log: true - ansible.builtin.shell: - ansible-vault view --vault-password-file <(cat <<<"{{ vault_pass.user_input }}") "{{ found_file }}" - register: values_secret_plaintext - when: is_encrypted - changed_when: false - -- name: Loads secrets file into the vault of a cluster - no_log: false - vault_load_secrets: - values_secrets: "{{ found_file }}" - check_missing_secrets: false - values_secret_template: "{{ secret_template }}" - when: not is_encrypted - -- name: Loads secrets file into the vault of a cluster - no_log: false - vault_load_secrets: - values_secrets_plaintext: "{{ values_secret_plaintext.stdout }}" - check_missing_secrets: false - values_secret_template: "{{ secret_template }}" - when: is_encrypted diff --git a/ansible/roles/vault_utils/tasks/vault_init.yaml b/ansible/roles/vault_utils/tasks/vault_init.yaml deleted file mode 100644 index 38e1e911..00000000 --- a/ansible/roles/vault_utils/tasks/vault_init.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -- name: Vault status check - ansible.builtin.include_tasks: vault_status.yaml - -# If the vault is already initialized we skip all the tasks below -- name: Is the vault initialized? - ansible.builtin.set_fact: - vault_initialized: "{{ vault_status['initialized'] | bool }}" - -# We need to retry here because the vault service might be starting -# and can return a 500 internal server until its state is fully ready -- name: Init vault operator - no_log: true - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: vault operator init -format=json - register: vault_init_json_out - until: vault_init_json_out is not failed - retries: 10 - delay: 15 - when: not vault_initialized - -- name: Set vault init output json fact - no_log: true - ansible.builtin.set_fact: - vault_init_json: "{{ vault_init_json_out.stdout | from_json }}" - when: not vault_initialized - -# We store the the operator unseal keys and root token to a secret inside -# the cluster when the vault was not already initialized *and* when -# unseal_from_cluster is set to true -- name: Save vault operator output (into a secret inside the cluster) - no_log: true - kubernetes.core.k8s: - state: present - definition: - apiVersion: v1 - kind: Secret - type: Opaque - metadata: - name: "{{ unseal_secret }}" - namespace: "{{ unseal_namespace }}" - data: - vault_data_json: "{{ vault_init_json | to_nice_json | b64encode }}" - when: - - not vault_initialized diff --git a/ansible/roles/vault_utils/tasks/vault_secrets_init.yaml b/ansible/roles/vault_utils/tasks/vault_secrets_init.yaml deleted file mode 100644 index 8a098a7c..00000000 --- a/ansible/roles/vault_utils/tasks/vault_secrets_init.yaml +++ /dev/null @@ -1,118 +0,0 @@ ---- -- name: Is secrets backend already enabled - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - bash -e -c "vault secrets list | grep -e '^{{ vault_base_path }}'" - register: secrets_enabled - failed_when: false - -- name: Create secrets backend kv-v2 - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: vault secrets enable -path="{{ vault_base_path }}" kv-v2 - when: secrets_enabled.rc != 0 - -- name: Is kubernetes backend already enabled - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - bash -e -c "vault auth list | grep -e '^{{ vault_hub }}'" - register: kubernetes_enabled - failed_when: false - -- name: Enable kubernetes backend on hub - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: "vault auth enable -path={{ vault_hub }} kubernetes" - when: kubernetes_enabled.rc != 0 - -- name: Get token from service account secret {{ external_secrets_ns }}/{{ external_secrets_secret }} - no_log: true - kubernetes.core.k8s_info: - kind: Secret - namespace: "{{ external_secrets_ns }}" - name: "{{ external_secrets_secret }}" - api_version: v1 - register: token_data - failed_when: token_data.resources | length == 0 - -- name: Set sa_token fact - no_log: true - ansible.builtin.set_fact: - sa_token: "{{ token_data.resources[0].data.token | b64decode }}" - -- name: Configure hub kubernetes backend - no_log: true - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: bash -e -c "vault write auth/{{ vault_hub }}/config token_reviewer_jwt={{ sa_token }} - kubernetes_host={{ vault_hub_kubernetes_host }} - kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt - issuer=https://kubernetes.default.svc" - -# This creates a {{ vault_global_policy }} policy that is applied to both hubs and spokes -- name: Configure VP global policy template - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - bash -e -c "echo \"path \\\"secret/data/{{ vault_global_policy }}/*\\\" { - capabilities = {{ vault_global_capabilities }} }\" > /tmp/policy-{{ vault_global_policy }}.hcl" - -- name: Configure VP global policy - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: "vault policy write {{ vault_global_policy }}-secret /tmp/policy-{{ vault_global_policy }}.hcl" - -- name: Configure VP pushsecrets policy template - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - bash -e -c "echo \"path \\\"secret/data/{{ vault_pushsecrets_policy }}/*\\\" { - capabilities = {{ vault_pushsecrets_capabilities }} }\" > /tmp/policy-{{ vault_pushsecrets_policy }}.hcl" - -- name: Add metadata path to the pushsecrets policy - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - bash -e -c "echo \"path \\\"secret/metadata/{{ vault_pushsecrets_policy }}/*\\\" { - capabilities = {{ vault_pushsecrets_capabilities }} }\" >> /tmp/policy-{{ vault_pushsecrets_policy }}.hcl" - -- name: Configure VP pushsecrets policy - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: "vault policy write {{ vault_pushsecrets_policy }}-secret /tmp/policy-{{ vault_pushsecrets_policy }}.hcl" - -- name: Configure policy template for hub - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - bash -e -c "echo \"path \\\"secret/data/{{ vault_hub }}/*\\\" { - capabilities = {{ vault_hub_capabilities }} }\" > /tmp/policy-{{ vault_hub }}.hcl" - -- name: Configure policy for hub - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: "vault policy write {{ vault_hub }}-secret /tmp/policy-{{ vault_hub }}.hcl" - -- name: Configure kubernetes role for hub - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - vault write auth/"{{ vault_hub }}"/role/"{{ vault_hub }}"-role - bound_service_account_names="{{ external_secrets_sa }}" - bound_service_account_namespaces="{{ external_secrets_ns }}" - policies="default,{{ vault_global_policy }}-secret,{{ vault_pushsecrets_policy }}-secret,{{ vault_hub }}-secret" ttl="{{ vault_hub_ttl }}" diff --git a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml deleted file mode 100644 index bafe490b..00000000 --- a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml +++ /dev/null @@ -1,228 +0,0 @@ ---- -- name: Find managed clusters - kubernetes.core.k8s_info: - kind: ManagedCluster - api_version: "cluster.open-cluster-management.io/v1" - register: managed_clusters - -- name: Set resource fact - ansible.builtin.set_fact: - resources: "{{ managed_clusters['resources'] }}" - -- name: Do nothing when no managed clusters are found - ansible.builtin.meta: end_play - when: resources | length == 0 or managed_clusters.failed or not managed_clusters.api_found - -- name: Loop over returned ACM managedclusters - ansible.builtin.set_fact: - clusters: "{{ clusters | default({}) | combine({item.metadata.name: {'caBundle': item.spec.managedClusterClientConfigs[0].caBundle | b64decode}}) }}" - loop: "{{ resources }}" - when: item.spec.managedClusterClientConfigs[0].caBundle is defined - loop_control: - label: "{{ item.metadata.name }}" - -- name: Extract ClusterGroup - ansible.builtin.set_fact: - clusters: "{{ clusters | default({}) | combine({item.metadata.name: {'clusterGroup': item.metadata.labels.clusterGroup}}, recursive=True) }}" - when: "'clusterGroup' in item.metadata.labels" - loop: "{{ resources }}" - loop_control: - label: "{{ item.metadata.name }}" - -- name: Fetch all ACM secrets - kubernetes.core.k8s_info: - kind: Secret - label_selectors: - - "apps.open-cluster-management.io/secret-type=acm-cluster" - register: acm_secrets - -- name: Set cleaned_acm_secrets fect - ansible.builtin.set_fact: - cleaned_acm_secrets: "{{ acm_secrets.resources | parse_acm_secrets }}" - -- name: Merge the two dicts together - ansible.builtin.set_fact: - clusters_info: "{{ clusters | default({}) | combine(cleaned_acm_secrets, recursive=True) }}" - -- name: Write out CAs - ansible.builtin.copy: - content: "{{ item.value['caBundle'] }}" - dest: "/tmp/{{ item.key }}.ca" - mode: "0640" - loop: "{{ clusters_info | dict2items }}" - when: item.value['caBundle'] is defined - loop_control: - label: "{{ item.key }}" - -# FIXME(bandini): validate_certs is false due to an ACM bug when using -# letsencrypt certificates with API endpoints: https://issues.redhat.com/browse/ACM-4398 -# We always verify the CA chain except when letsencrypt.api_endpoint is set to true -- name: If we are using letsencrypt on the API endpoints we cannot use the validate_certs later - ansible.builtin.set_fact: - validate_certs_api_endpoint: "{{ not letsencrypt.api_endpoint | default(True) | bool }}" - -- name: Fetch remote ansible to remote cluster - kubernetes.core.k8s_info: - api_key: "{{ item.value['bearerToken'] }}" - ca_cert: /tmp/{{ item.key }}.ca - host: "{{ item.value['server_api'] }}" - kind: Secret - namespace: "{{ external_secrets_ns }}" - name: "{{ external_secrets_secret }}" - api_version: v1 - validate_certs: "{{ validate_certs_api_endpoint }}" - register: remote_external_secrets_sa - # We are allowed to ignore errors here because a spoke might be down or unreachable - # if a spoke is not reachable then its ['token'] field will not be set which - # will leave the ['esoToken'] field empty in the dict which will make it so that - # the spoke gets skipped - ignore_errors: true - # We add no_log: true here because in case of a remote failure secret bits might - # end up in the log. Unfortunately ansible is currently not easily able to control - # output in a loop (see - # https://serverfault.com/questions/1059530/how-to-not-print-items-in-an-ansible-loop-error-without-no-log) - no_log: true - when: - - clusters_info[item.key]['bearerToken'] is defined - - clusters_info[item.key]['server_api'] is defined - - clusters_info[item.key]['caBundle'] is defined - loop: "{{ clusters_info | dict2items }}" - loop_control: - label: "{{ item.key }}" - -# 'token' will be empty if the remote cluster has no golang-external-secret -# app configured and running -- name: Loop over returned ESO tokens - ansible.builtin.set_fact: - clusters_info: "{{ clusters_info | default({}) | combine({item['item']['key']: {'esoToken': item['resources'][0]['data']['token'] | b64decode}}, recursive=True) }}" - loop: "{{ remote_external_secrets_sa.results }}" - when: item['resources'][0]['data']['token'] is defined - loop_control: - label: "{{ item['item']['key'] }}" - -# At this point clusters_info contains a per cluster hash table with *all* the right attributes. For example: -# "mcg-one": { -# "bearerToken": "ey...", -# "caBundle": "-----BEGIN CERTIFICATE-----\nMIIDMjCCA", -# "clusterGroup": "group-one", -# "cluster_fqdn": "mcg-one.blueprints.rhecoeng.com", -# "vault_path": "hub" (when the hub) and the cluster_fqdn when not hub, -# "esoToken": (optional) only if there was an external golang-external-secrets namespace+service account -# "name": "mcg-one", -# "server_api": "https://api.mcg-one.blueprints.rhecoeng.com:6443", -# "tlsClientConfig": { -# "insecure": true -# } -# } -- name: Dump CABundles into the vault - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: bash -e -c "echo '{{ item.value['caBundle'] }}' > /tmp/{{ item.value['vault_path'] }}.ca" - loop: "{{ clusters_info | dict2items }}" - when: - - item.value['esoToken'] is defined - - item.key != "local-cluster" - loop_control: - label: "{{ item.key }}" - -- name: Is kubernetes backend already enabled - no_log: true - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: bash -e -c "if vault auth list | grep -e ^'{{ item.value['vault_path'] }}'; then - echo done; else - vault auth enable -path='{{ item.value['vault_path'] }}' kubernetes; fi" - loop: "{{ clusters_info | dict2items }}" - when: - - item.value['esoToken'] is defined - - item.key != "local-cluster" - loop_control: - label: "{{ item.key }}" - -- name: Configure kubernetes backend - no_log: true - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: bash -e -c "vault write auth/{{ item.value['vault_path'] }}/config - token_reviewer_jwt=\"{{ item.value['esoToken'] }}\" - kubernetes_host=\"{{ item.value['server_api'] }}\" - kubernetes_ca_cert=@/tmp/{{ item.value['vault_path'] }}.ca" - loop: "{{ clusters_info | dict2items }}" - when: - - item.value['esoToken'] is defined - - item.key != "local-cluster" - loop_control: - label: "{{ item.key }}" - -- name: Configure spoke policy template - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - bash -e -c "echo \"path \\\"secret/data/{{ item.value['vault_path'] }}/*\\\" { - capabilities = {{ vault_spoke_capabilities }} }\" > /tmp/policy-{{ item.value['vault_path'] }}.hcl" - loop: "{{ clusters_info | dict2items }}" - when: - - item.value['esoToken'] is defined - - item.key != "local-cluster" - loop_control: - label: "{{ item.key }}" - -- name: Configure spoke pushsecrets policy template - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - bash -e -c "echo \"path \\\"secret/data/{{ vault_pushsecrets_policy }}/*\\\" { - capabilities = {{ vault_pushsecrets_capabilities }} }\" >> /tmp/policy-{{ item.value['vault_path'] }}.hcl" - loop: "{{ clusters_info | dict2items }}" - when: - - item.value['esoToken'] is defined - - item.key != "local-cluster" - loop_control: - label: "{{ item.key }}" - -- name: Configure spoke pushsecrets metadata policy template - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - bash -e -c "echo \"path \\\"secret/metadata/{{ vault_pushsecrets_policy }}/*\\\" { - capabilities = {{ vault_pushsecrets_capabilities }} }\" >> /tmp/policy-{{ item.value['vault_path'] }}.hcl" - loop: "{{ clusters_info | dict2items }}" - when: - - item.value['esoToken'] is defined - - item.key != "local-cluster" - loop_control: - label: "{{ item.key }}" - -- name: Configure policy for spokes - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: "vault policy write {{ item.value['vault_path'] }}-secret /tmp/policy-{{ item.value['vault_path'] }}.hcl" - loop: "{{ clusters_info | dict2items }}" - when: - - item.value['esoToken'] is defined - - item.key != "local-cluster" - loop_control: - label: "{{ item.key }}" - -- name: Configure kubernetes role for spokes - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: > - vault write auth/"{{ item.value['vault_path'] }}"/role/"{{ item.value['vault_path'] }}"-role - bound_service_account_names="{{ external_secrets_sa }}" - bound_service_account_namespaces="{{ external_secrets_ns }}" - policies="default,{{ vault_global_policy }}-secret,{{ vault_pushsecrets_policy }}-secret,{{ item.value['vault_path'] }}-secret" ttl="{{ vault_spoke_ttl }}" - loop: "{{ clusters_info | dict2items }}" - when: - - item.value['esoToken'] is defined - - item.key != "local-cluster" - loop_control: - label: "{{ item.key }}" diff --git a/ansible/roles/vault_utils/tasks/vault_status.yaml b/ansible/roles/vault_utils/tasks/vault_status.yaml deleted file mode 100644 index 9dc3e426..00000000 --- a/ansible/roles/vault_utils/tasks/vault_status.yaml +++ /dev/null @@ -1,61 +0,0 @@ ---- -# Registers a variable valled vault_status containing the vault's status json dict -- name: Check for vault namespace - kubernetes.core.k8s_info: - kind: Namespace - name: "{{ vault_ns }}" - register: vault_ns_rc - until: vault_ns_rc.resources | length > 0 - retries: 20 - delay: 45 - -- name: Check if the vault pod is present - kubernetes.core.k8s_info: - kind: Pod - namespace: "{{ vault_ns }}" - name: "{{ vault_pod }}" - register: vault_pod_rc - until: vault_pod_rc.resources | length > 0 - retries: 20 - delay: 45 - -# This needs retrying because during startup we can just get -# Failed to execute on pod vault-0 due to : (0)\nReason: Handshake status 500 Internal Server Error -# In the above case there is no 'rc' in vault_status. So first we wait for 'rc' to show up and ignore -# any errors, and then we bail out if rc is 2 as it means the vault is already initialized -- name: Check for the vault status - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: vault status -format=json - register: vault_status_json - until: "'rc' in vault_status_json" - retries: 20 - delay: 45 - failed_when: "'stdout_lines' not in vault_status_json" - -- name: Set vault status output json fact - ansible.builtin.set_fact: - vault_status: "{{ vault_status_json.stdout | from_json }}" - when: vault_status_json.stdout_lines | length > 0 - -- name: List Vault pods - kubernetes.core.k8s_info: - namespace: "{{ vault_ns }}" - kind: Pod - label_selectors: - - "component = server" - register: vault_pods_list - -- name: "Get pods" - ansible.builtin.set_fact: - vault_pods: "{{ vault_pods + [item.metadata.name] }}" - loop: "{{ vault_pods_list.resources }}" - loop_control: - label: "{{ item.metadata.name }}" - vars: - vault_pods: [] - -- name: "Followers" - ansible.builtin.set_fact: - followers: "{{ vault_pods | difference(vault_pod) }}" diff --git a/ansible/roles/vault_utils/tasks/vault_unseal.yaml b/ansible/roles/vault_utils/tasks/vault_unseal.yaml deleted file mode 100644 index 43232ac7..00000000 --- a/ansible/roles/vault_utils/tasks/vault_unseal.yaml +++ /dev/null @@ -1,88 +0,0 @@ ---- -- name: Vault status check - ansible.builtin.include_tasks: vault_status.yaml - -# If the vault is already unsealed we skip all the tasks below -- name: Is the vault sealed? - ansible.builtin.set_fact: - vault_sealed: "{{ vault_status['sealed'] | bool }}" - -# We reparse the json vault init secret in case unseal was called without operator init before -- name: Parse vaultkeys - kubernetes.core.k8s_info: - kind: Secret - namespace: "{{ unseal_namespace }}" - name: "{{ unseal_secret }}" - api_version: v1 - register: vault_init_data - when: vault_sealed - -- name: Does the vaultkeys secret exist? - ansible.builtin.set_fact: - vaultkeys_exists: "{{ vault_init_data.resources | length > 0 }}" - when: vault_sealed - -- name: Vaultkeys does not exist and the vault is sealed, so exit - ansible.builtin.meta: end_play - when: - - vault_sealed - - not vaultkeys_exists - -- name: Set vault init json - ansible.builtin.set_fact: - vault_init_json: "{{ vault_init_data.resources[0].data.vault_data_json | b64decode | from_json }}" - when: vault_sealed - -- name: Set root token and unseal_keys - ansible.builtin.set_fact: - root_token: "{{ vault_init_json['root_token'] }}" - unseal_keys: "{{ vault_init_json['unseal_keys_hex'] }}" - when: vault_sealed - -- name: Unseal leader - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: vault operator unseal "{{ item }}" - loop: "{{ unseal_keys }}" - loop_control: - extended: true - label: "Unsealing with key {{ ansible_loop.index }}" - when: vault_sealed - -- name: Join Raft cluster - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ item }}" - command: vault operator raft join http://{{ vault_pod }}.{{ vault_ns }}-internal:8200 - register: join_raft_cluster_out - until: join_raft_cluster_out is not failed - retries: 10 - delay: 15 - loop: "{{ followers }}" - loop_control: - extended: true - label: "Joining Raft Cluster on http://{{ vault_pod }}.{{ vault_ns }}-internal:8200" - when: - - vault_sealed - - followers | length > 0 - -- name: Unseal followers - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ item.0 }}" - command: vault operator unseal "{{ item.1 }}" - loop: "{{ followers | product(unseal_keys) | list }}" - loop_control: - extended: true - label: "Unsealing {{ item.0 }} with key {{ ansible_loop.index }}" - when: - - vault_sealed - - followers | length > 0 - -- name: Login into vault - kubernetes.core.k8s_exec: - namespace: "{{ vault_ns }}" - pod: "{{ vault_pod }}" - command: vault login "{{ root_token }}" - when: vault_sealed diff --git a/ansible/roles/vault_utils/tests/inventory b/ansible/roles/vault_utils/tests/inventory deleted file mode 100644 index 878877b0..00000000 --- a/ansible/roles/vault_utils/tests/inventory +++ /dev/null @@ -1,2 +0,0 @@ -localhost - diff --git a/ansible/roles/vault_utils/tests/test.yml b/ansible/roles/vault_utils/tests/test.yml deleted file mode 100644 index b4da5c68..00000000 --- a/ansible/roles/vault_utils/tests/test.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: Test Play - hosts: localhost - remote_user: root - roles: - - vault_utils diff --git a/ansible/roles/vault_utils/values-secrets.v1.schema.json b/ansible/roles/vault_utils/values-secrets.v1.schema.json deleted file mode 100644 index 3cb8c530..00000000 --- a/ansible/roles/vault_utils/values-secrets.v1.schema.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "$ref": "#/definitions/valuesSecretsV1", - "meta:license": [ - "Copyright 2022 Red Hat, Inc. All rights reserved.", - "This file is licensed to you under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License. You may obtain a copy", - "of the License at http://www.apache.org/licenses/LICENSE-2.0" - ], - "title": "Hybrid Cloud Patterns - values-secret.yaml files schema V1", - "description": "This schema defines the values-secret.yaml file as used by [Validated Patterns](https://hybrid-cloud-patterns.io)", - "type": "object", - "examples": [], - "definitions": { - "valuesSecretsV1": { - "title": "Values Secrets V1 Format", - "type": "object", - "additionalProperties": true, - "properties": { - "version": { - "type": [ "string", "null" ], - "description": "Version of the secret specification", - "default": "1.0" - } - }, - "patternProperties": { - "secrets[a-z0-9.]*$": { - "type": "object", - "additionalProperties": true - }, - "files[a-z0-9.]*$": { - "type": "object", - "additionalProperties": true - } - } - } - } -} diff --git a/ansible/roles/vault_utils/values-secrets.v2.schema.json b/ansible/roles/vault_utils/values-secrets.v2.schema.json deleted file mode 100644 index c8b5c020..00000000 --- a/ansible/roles/vault_utils/values-secrets.v2.schema.json +++ /dev/null @@ -1,335 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$ref": "#/definitions/valuesSecretsV2", - "meta:license": [ - "Copyright 2022 Red Hat, Inc. All rights reserved.", - "This file is licensed to you under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License. You may obtain a copy", - "of the License at http://www.apache.org/licenses/LICENSE-2.0" - ], - "title": "Hybrid Cloud Patterns - values-secret.yaml files schema V2", - "description": "This schema defines the values-secret.yaml file as used by [Validated Patterns](https://hybrid-cloud-patterns.io)", - "type": "object", - "examples": [ - { - "version": "2.0", - "backingStore": "vault", - "vaultPolicies": { - "basicPolicy": "length=10\nrule \"charset\" { charset = \"abcdefghijklmnopqrstuvwxyz\" min-chars = 1 }\nrule \"charset\" { charset = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" min-chars = 1 }\nrule \"charset\" { charset = \"0123456789\" min-chars = 1 }\n", - "advancedPolicy": "length=20\nrule \"charset\" { charset = \"abcdefghijklmnopqrstuvwxyz\" min-chars = 1 }\nrule \"charset\" { charset = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" min-chars = 1 }\nrule \"charset\" { charset = \"0123456789\" min-chars = 1 }\nrule \"charset\" { charset = \"!@#$%^&*\" min-chars = 1 }\n" - }, - "secrets": [ - { - "name": "config-demo", - "vaultMount": "secret", - "vaultPrefixes": [ - "region-one", - "snowflake.blueprints.rhecoeng.com" - ], - "fields": [ - { - "name": "secret", - "onMissingValue": "generate", - "override": true, - "vaultPolicy": "basicPolicy" - }, - { - "name": "secretprompt", - "value": null, - "onMissingValue": "prompt", - "prompt": "Please specify the password for application ABC" - }, - { - "name": "secretprompt2", - "value": "defaultvalue", - "onMissingValue": "prompt", - "prompt": "Please specify the API key for XYZ" - }, - { - "name": "secretfile", - "path": "/tmp/ca.crt", - "onMissingValue": "prompt", - "prompt": "Insert path to Certificate Authority" - }, - { - "name": "ca_crt", - "path": "/tmp/ca.crt", - "onMissingValue": "error" - }, - { - "name": "ca_crt_b64", - "path": "/tmp/ca.crt", - "base64": true, - "onMissingValue": "prompt" - } - ] - }, - { - "name": "config-demo2", - "vaultPrefixes": [ - "region-one", - "snowflake.blueprints.rhecoeng.com" - ], - "fields": [ - { - "name": "ca_crt2", - "path": null, - "onMissingValue": "prompt" - }, - { - "name": "ca_crt", - "path": "/tmp/ca.crt", - "onMissingValue": "error" - } - ] - } - ] - } - ], - "definitions": { - "valuesSecretsV2": { - "type": "object", - "additionalProperties": false, - "properties": { - "version": { - "type": [ "string", "null" ], - "description": "Version of the secret specification", - "default": "1.0" - }, - "backingStore": { - "type": "string", - "description": "Secrets backing store type", - "default": "vault" - }, - "vaultPolicies": { - "$ref": "#/definitions/VaultPolicies", - "description": "A dictionary of {name}:{policy} of custom vault password policies" - }, - "secretStoreNamespace": { - "type": "string", - "description": "Namespace to store secrets in for kubernetes loader", - "default": "validated-patterns-secrets" - }, - "defaultLabels": { - "type": "object", - "description": "Default labels to add to secret objects for kubernetes loader" - }, - "defaultAnnotations": { - "type": "object", - "description": "Default labels to add to secret objects for kubernetes loader" - }, - "secrets": { - "$ref": "#/definitions/Secrets", - "description": "The list of actual secrets to be uploaded in the vault" - } - }, - "required": [ - "secrets" - ], - "title": "Values Secrets V2 Format" - }, - "VaultPolicies": { - "type": "object", - "description": "A dictionary of {name}:{policy} of custom vault password policies", - "items": { - "$ref": "#/definitions/VaultPolicy" - }, - "examples": [ - { - "vaultPolicies": { - "basicPolicy": "length=10\nrule \"charset\" { charset = \"abcdefghijklmnopqrstuvwxyz\" min-chars = 1 }\nrule \"charset\" { charset = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" min-chars = 1 }\nrule \"charset\" { charset = \"0123456789\" min-chars = 1 }\n", - "advancedPolicy": "length=20\nrule \"charset\" { charset = \"abcdefghijklmnopqrstuvwxyz\" min-chars = 1 }\nrule \"charset\" { charset = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" min-chars = 1 }\nrule \"charset\" { charset = \"0123456789\" min-chars = 1 }\nrule \"charset\" { charset = \"!@#$%^&*\" min-chars = 1 }\n" - } - } - ] - }, - "VaultPolicy": { - "type": "string", - "description": "A password policy to be created in the vault. See https://developer.hashicorp.com/vault/docs/concepts/password-policies" - }, - "Secrets": { - "type": "array", - "description": "The list of secrets to be injected into the vault", - "items": { - "$ref": "#/definitions/Secret" - } - }, - "Secret": { - "type": "object", - "description": "The single secret to be injected into the vault", - "additionalProperties": false, - "required": [ "name", "fields" ], - "properties": { - "name": { - "type": "string", - "description": "This is the name of the top level key that will be created at the vaultMount point and that will contain one secret per field inside its attributes" - }, - "vaultMount": { - "type": "string", - "description": "This is the vault -mount=<...> mount point used in vault commands", - "default": "secret" - }, - "vaultPrefixes": { - "type": "array", - "description": "This is the list of prefixes the secret will be uploaded to. It defaults to ['hub'] when not specified", - "items": { - "type": "string", - "minItems": 1, - "uniqueItems": true - }, - "default": [ "hub" ] - }, - "targetNamespaces": { - "type": "array", - "description": "The namespace(s) that the secret will be injected into, ignored by configs using ESO", - "items": { - "type": "string", - "minItems": 1, - "uniqueItems": true - } - }, - "annotations": { - "type": "object", - "description": "Annotations to add to the kubernetes secret object, which override defaults" - }, - "labels": { - "type": "object", - "description": "Labels to add to the kubernetes secret object, which override defaults" - }, - "fields": { - "type": "array", - "description": "This is the list of actual secret material that will be placed in a vault key's attributes", - "items": { - "type": "object", - "$ref": "#/definitions/Field", - "minItems": 1, - "uniqueItems": true - } - } - } - }, - "Field": { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string", - "description": "This is the name of the attribute inside vault" - }, - "onMissingValue": { - "type": "string", - "default": "error", - "description": "'error' will generate an error if the secret (via value or via path attributes) are not defined. 'generate' will create a secret using a defined vaultPolicy. 'prompt' will ask the user for input and it requires to set a value or a path depending if the user should input a secret or a path to a secret file. Non-null entries represent the default value when prompted.", - "enum": [ - "error", - "generate", - "prompt" - ] - }, - "prompt": { - "type": "string", - "description": "Represents the prompt used when onMissingValue is set to prompt" - }, - "value": { - "type": [ - "string", - "null" - ], - "description": "Is the value of a secret. Represents the default value when onMissingValue is set to prompt" - }, - "path": { - "type": [ - "string", - "null" - ], - "description": "Is the path to a secret file. Represents the default path when onMissingValue is set to prompt" - }, - "ini_file": { - "type": [ - "string", - "null" - ], - "description": "Is the path to an ini_file containing secret material" - }, - "ini_section": { - "type": [ - "string", - "null" - ], - "description": "Is the section in an ini file where a user-defined key will be looked up", - "default": "default" - }, - "ini_key": { - "type": [ - "string", - "null" - ], - "description": "Is the key inside a section in an inifile whose value will be used" - }, - "vaultPolicy": { - "type": "string", - "description": "When onMissingValue is set to 'generate', uses this policy to create the secret inside the vault directly" - }, - "base64": { - "type": "boolean", - "description": "Before uploading the secret the content is base-64 encoded. It is recommended to set this to true when dealing with files", - "default": "false" - }, - "override": { - "type": "boolean", - "description": "When onMissingValue is set to 'generate' and the secret already exists in the vault update it", - "default": "false" - } - }, - "dependentRequired": { - "ini_file": ["ini_key"] - }, - "allOf": [ - { - "if": { - "properties": { "onMissingValue": { "enum": ["prompt"] } } - }, - "then": { - "oneOf": [ - { - "required": [ "path" ] - }, - { - "required": [ "value" ] - } - ] - } - }, - { - "if": { - "properties": { "onMissingValue": { "enum": ["generate"] } } - }, - "then": { - "required": [ "vaultPolicy" ] - } - }, - { - "if": { - "properties": { "onMissingValue": { "enum": ["error"] } } - }, - "then": { - "oneOf": [ - { - "required": [ "path" ] - }, - { - "required": [ "ini_file" ] - }, - { - "required": [ "value" ] - } - ] - } - } - ] - } - } -} diff --git a/ansible/roles/vault_utils/vars/main.yml b/ansible/roles/vault_utils/vars/main.yml deleted file mode 100644 index f6e02b93..00000000 --- a/ansible/roles/vault_utils/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for vault_utils diff --git a/ansible/tests/unit/test_ini_file.py b/ansible/tests/unit/test_ini_file.py deleted file mode 100644 index 6c30fdbb..00000000 --- a/ansible/tests/unit/test_ini_file.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Simple module to test ini parsing function -""" - -import os -import sys -import unittest - -# TODO(bandini): I could not come up with something better to force the imports to be existing -# when we 'import vault_load_secrets' -sys.path.insert(1, "./ansible/plugins/module_utils") -sys.path.insert(1, "./ansible/plugins/modules") -import load_secrets_common # noqa: E402 - - -class TestMyModule(unittest.TestCase): - - def setUp(self): - self.testdir_v2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), "v2") - - def test_ensure_ini_file_parsed_correctly(self): - f = os.path.join(self.testdir_v2, "aws-example.ini") - key_id = load_secrets_common.get_ini_value(f, "default", "aws_access_key_id") - access_key = load_secrets_common.get_ini_value( - f, "default", "aws_secret_access_key" - ) - self.assertEqual(key_id, "A123456789012345678A") - self.assertEqual(access_key, "A12345678901234567890123456789012345678A") - - def test_ensure_ini_file_missing_value_is_none(self): - f = os.path.join(self.testdir_v2, "aws-example.ini") - missing_id = load_secrets_common.get_ini_value(f, "default", "nonexisting") - self.assertEqual(missing_id, None) - - def test_ensure_ini_file_missing_section_is_none(self): - f = os.path.join(self.testdir_v2, "aws-example.ini") - missing_id = load_secrets_common.get_ini_value(f, "nonexisting", "nonexisting") - self.assertEqual(missing_id, None) - - -if __name__ == "__main__": - unittest.main() diff --git a/ansible/tests/unit/test_parse_secrets.py b/ansible/tests/unit/test_parse_secrets.py deleted file mode 100644 index 2dab5716..00000000 --- a/ansible/tests/unit/test_parse_secrets.py +++ /dev/null @@ -1,983 +0,0 @@ -# Copyright 2022, 2023 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Simple module to test parse_secret_info -""" - -import base64 -import configparser -import json -import os -import sys -import unittest -from unittest import mock -from unittest.mock import patch - -from ansible.module_utils import basic -from ansible.module_utils.common.text.converters import to_bytes -from test_util_datastructures import ( - DEFAULT_KUBERNETES_METADATA, - DEFAULT_KUBERNETES_SECRET_OBJECT, - DEFAULT_PARSED_SECRET_VALUE, - DEFAULT_VAULT_POLICIES, -) - -# from unittest.mock import call, patch - -# TODO(bandini): I could not come up with something better to force the imports to be existing -# when we "import parse_secrets_info" -sys.path.insert(1, "./ansible/plugins/module_utils") -sys.path.insert(1, "./ansible/plugins/modules") - -import load_secrets_common # noqa: E402 - -sys.modules["ansible.module_utils.load_secrets_common"] = load_secrets_common - -import parse_secrets_v2 # noqa: E402 - -sys.modules["ansible.module_utils.parse_secrets_v2"] = parse_secrets_v2 - -import parse_secrets_info # noqa: E402 - -sys.modules["ansible.modules.parse_secrets_info"] = parse_secrets_info - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({"ANSIBLE_MODULE_ARGS": args}) - basic._ANSIBLE_ARGS = to_bytes(args) - - -class BytesEncoder(json.JSONEncoder): - - def default(self, o): - if isinstance(o, bytes): - return base64.b64encode(o).decode("ascii") - else: - return super().default(o) - - -def json_str(a): - return json.dumps(a, sort_keys=True, cls=BytesEncoder) - - -def ds_eq(a, b): - """ - This function takes two arbitrary data structures, sorts their keys, stringifies them into JSON - and compares them. The idea here is to test data structure difference without having to write - an involved recursive data structure parser. If the function returns true, the two data - structures are equal. - """ - print("a=" + json_str(a)) - print("b=" + json_str(b)) - return json_str(a) == json_str(b) - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - - pass - - -def exit_json(*args, **kwargs): - """function to patch over exit_json; package return data into an exception""" - if "changed" not in kwargs: - kwargs["changed"] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): - """function to patch over fail_json; package return data into an exception""" - kwargs["failed"] = True - kwargs["args"] = args - raise AnsibleFailJson(kwargs) - - -@mock.patch("getpass.getpass") -class TestMyModule(unittest.TestCase): - - def create_inifile(self): - self.inifile = open("/tmp/awscredentials", "w") - config = configparser.ConfigParser() - config["default"] = { - "aws_access_key_id": "123123", - "aws_secret_access_key": "abcdefghi", - } - config["foobar"] = { - "aws_access_key_id": "345345", - "aws_secret_access_key": "rstuvwxyz", - } - with self.inifile as configfile: - config.write(configfile) - - def create_testbinfile(self): - with open(self.binfilename, "wb") as f: - f.write(bytes([8, 6, 7, 5, 3, 0, 9])) - f.close() - - def setUp(self): - self.binfilename = "/tmp/testbinfile.bin" - self.mock_module_helper = patch.multiple( - basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json - ) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.testdir_v2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), "v2") - self.testfile = open("/tmp/ca.crt", "w") - self.create_inifile() - self.create_testbinfile() - # For ~/expanduser tests - self.orig_home = os.environ["HOME"] - os.environ["HOME"] = self.testdir_v2 - - def tearDown(self): - os.environ["HOME"] = self.orig_home - self.testfile.close() - try: - os.remove("/tmp/ca.crt") - os.remove(self.binfilename) - # os.remove("/tmp/awscredentials") - except OSError: - pass - - def get_file_as_stdout(self, filename, openmode="r"): - with open(filename, mode=openmode, encoding="utf-8") as f: - return f.read() - - def test_module_fail_when_required_args_missing(self, getpass): - with self.assertRaises(AnsibleFailJson): - set_module_args({}) - parse_secrets_info.main() - - def test_module_parse_base(self, getpass): - getpass.return_value = "/tmp/ca.crt" - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-base.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - } - ) - parse_secrets_info.main() - - ret = result.exception.args[0] - self.assertTrue( - (ret["failed"] is False) - and (ret["changed"] is False) - and (len(ret["parsed_secrets"])) == 1 - and (len(ret["kubernetes_secret_objects"]) == 0) - ) - - def test_module_parse_base_parsed_secrets(self, getpass): - getpass.return_value = "/tmp/ca.crt" - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-base.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - } - ) - parse_secrets_info.main() - - vp = DEFAULT_VAULT_POLICIES | { - "basicPolicy": 'length=10\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\n', # noqa: E501 - "advancedPolicy": 'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n', # noqa: E501 - } - - # Beware reading this structure aloud to your cat... - pspsps = { - "config-demo": DEFAULT_PARSED_SECRET_VALUE - | { - "name": "config-demo", - "fields": { - "secret": None, - "secret2": "/tmp/ca.crt", - "ca_crt": "", - "ca_crt2": "", - }, - "base64": ["ca_crt2"], - "generate": ["secret"], - "override": ["secret"], - "vault_policies": { - "secret": "basicPolicy", - }, - "vault_prefixes": [ - "region-one", - "snowflake.blueprints.rhecoeng.com", - ], - "paths": { - "ca_crt": "/tmp/ca.crt", - "ca_crt2": "/tmp/ca.crt", - }, - }, - } - - ret = result.exception.args[0] - self.assertTrue( - (ret["failed"] is False) - and (ret["changed"] is False) - and (ds_eq(vp, ret["vault_policies"])) - and (ds_eq(pspsps, ret["parsed_secrets"])) - ) - - def test_module_parsed_secret_ini_files(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-ini-file.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - } - ) - parse_secrets_info.main() - - ps = { - "aws": DEFAULT_PARSED_SECRET_VALUE - | { - "name": "aws", - "fields": { - "aws_access_key_id": "123123", - "aws_secret_access_key": "abcdefghi", - }, - "ini_file": { - "aws_access_key_id": { - "ini_file": "/tmp/awscredentials", - "ini_section": "default", - "ini_key": "aws_access_key_id", - }, - "aws_secret_access_key": { - "ini_file": "/tmp/awscredentials", - "ini_section": "default", - "ini_key": "aws_secret_access_key", - }, - }, - }, - "awsfoobar": DEFAULT_PARSED_SECRET_VALUE - | { - "name": "awsfoobar", - "fields": { - "aws_access_key_id": "345345", - "aws_secret_access_key": "rstuvwxyz", - }, - "ini_file": { - "aws_access_key_id": { - "ini_file": "/tmp/awscredentials", - "ini_section": "foobar", - "ini_key": "aws_access_key_id", - }, - "aws_secret_access_key": { - "ini_file": "/tmp/awscredentials", - "ini_section": "foobar", - "ini_key": "aws_secret_access_key", - }, - }, - }, - } - - ret = result.exception.args[0] - self.assertTrue( - (ret["failed"] is False) - and (ret["changed"] is False) - and (len(ret["parsed_secrets"]) == 2) - and (ds_eq(ps, ret["parsed_secrets"])) - ) - - def test_module_parsed_secret_ini_files_base64(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-ini-file-b64.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - } - ) - parse_secrets_info.main() - - ps = { - "aws": DEFAULT_PARSED_SECRET_VALUE - | { - "name": "aws", - "fields": { - "aws_access_key_id": "A123456789012345678A", - "aws_secret_access_key": "A12345678901234567890123456789012345678A", - }, - "ini_file": { - "aws_access_key_id": { - "ini_file": f"{os.environ['HOME']}/aws-example.ini", - "ini_section": "default", - "ini_key": "aws_access_key_id", - }, - "aws_secret_access_key": { - "ini_file": f"{os.environ['HOME']}/aws-example.ini", - "ini_section": "default", - "ini_key": "aws_secret_access_key", - }, - }, - }, - "awsb64": DEFAULT_PARSED_SECRET_VALUE - | { - "name": "awsb64", - "fields": { - "aws_access_key_id": "QTEyMzQ1Njc4OTAxMjM0NTY3OEE=", - "aws_secret_access_key": "QTEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4QQ==", - }, - "base64": [ - "aws_access_key_id", - "aws_secret_access_key", - ], - "ini_file": { - "aws_access_key_id": { - "ini_file": f"{os.environ['HOME']}/aws-example.ini", - "ini_section": "default", - "ini_key": "aws_access_key_id", - }, - "aws_secret_access_key": { - "ini_file": f"{os.environ['HOME']}/aws-example.ini", - "ini_section": "default", - "ini_key": "aws_secret_access_key", - }, - }, - }, - } - - ret = result.exception.args[0] - self.assertTrue( - (ret["failed"] is False) - and (ret["changed"] is False) - and (len(ret["parsed_secrets"]) == 2) - and (len(ret["kubernetes_secret_objects"]) == 0) - and (ds_eq(ps, ret["parsed_secrets"])) - ) - - def test_module_parsed_secret_ini_files_base64_kubernetes(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-ini-file-b64.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - - ps = { - "aws": DEFAULT_PARSED_SECRET_VALUE - | { - "name": "aws", - "fields": { - "aws_access_key_id": "A123456789012345678A", - "aws_secret_access_key": "A12345678901234567890123456789012345678A", - }, - "ini_file": { - "aws_access_key_id": { - "ini_file": f"{os.environ['HOME']}/aws-example.ini", - "ini_section": "default", - "ini_key": "aws_access_key_id", - }, - "aws_secret_access_key": { - "ini_file": f"{os.environ['HOME']}/aws-example.ini", - "ini_section": "default", - "ini_key": "aws_secret_access_key", - }, - }, - }, - "awsb64": DEFAULT_PARSED_SECRET_VALUE - | { - "name": "awsb64", - "fields": { - "aws_access_key_id": "QTEyMzQ1Njc4OTAxMjM0NTY3OEE=", - "aws_secret_access_key": "QTEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4QQ==", - }, - "base64": [ - "aws_access_key_id", - "aws_secret_access_key", - ], - "ini_file": { - "aws_access_key_id": { - "ini_file": f"{os.environ['HOME']}/aws-example.ini", - "ini_section": "default", - "ini_key": "aws_access_key_id", - }, - "aws_secret_access_key": { - "ini_file": f"{os.environ['HOME']}/aws-example.ini", - "ini_section": "default", - "ini_key": "aws_secret_access_key", - }, - }, - }, - } - - ret = result.exception.args[0] - self.assertTrue( - (ret["failed"] is False) - and (ret["changed"] is False) - and (len(ret["parsed_secrets"]) == 2) - and (len(ret["kubernetes_secret_objects"]) == 2) - and (ds_eq(ps, ret["parsed_secrets"])) - ) - - def test_module_default_labels(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-default-labels.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - - ret = result.exception.args[0] - self.assertTrue( - ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "test-secret", - "labels": {"testlabel": "4"}, - "namespace": "validated-patterns-secrets", - }, - "stringData": {"username": "user"}, - }, - ) - ) - - def test_module_override_labels(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-override-labels.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - ret = result.exception.args[0] - self.assertTrue( - ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "test-secret", - "labels": {"overridelabel": "42"}, - }, - "stringData": {"username": "user"}, - }, - ) - ) - - def test_module_override_namespace(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-override-namespace.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - ret = result.exception.args[0] - self.assertTrue( - len(ret["kubernetes_secret_objects"]) == 1 - and ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "test-secret", - "namespace": "overridden-namespace", - }, - "stringData": {"username": "user"}, - }, - ) - ) - - def test_module_none_extra_namespaces(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-more-namespaces.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "none", - } - ) - parse_secrets_info.main() - ret = result.exception.args[0] - self.assertTrue( - len(ret["kubernetes_secret_objects"]) == 2 - and ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "test-secret", - "namespace": "default", - }, - "stringData": {"username": "user"}, - }, - ) - and ds_eq( - ret["kubernetes_secret_objects"][1], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "test-secret", - "namespace": "extra", - }, - "stringData": {"username": "user"}, - }, - ) - ) - - def test_module_override_type_kubernetes(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-override-type.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - ret = result.exception.args[0] - self.assertTrue( - len(ret["kubernetes_secret_objects"]) == 1 - and ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "type": "user-specified", - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "test-secret", - }, - "stringData": {"username": "user"}, - }, - ) - ) - - def test_module_override_type_none(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-override-type-none.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "none", - } - ) - parse_secrets_info.main() - ret = result.exception.args[0] - self.assertTrue( - len(ret["kubernetes_secret_objects"]) == 1 - and ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "type": "user-specified", - "metadata": DEFAULT_KUBERNETES_METADATA - | {"name": "test-secret", "namespace": "default"}, - "stringData": {"username": "user"}, - }, - ) - ) - - def test_module_secret_file_contents(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-file-contents.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - ret = result.exception.args[0] - self.assertTrue( - len(ret["kubernetes_secret_objects"]) == 1 - and ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "test-secret", - }, - "stringData": {"username": "This space intentionally left blank\n"}, - }, - ) - ) - - def test_module_secret_file_contents_b64(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-file-contents-b64.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - ret = result.exception.args[0] - self.assertTrue( - len(ret["kubernetes_secret_objects"]) == 1 - and ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "test-secret", - }, - "stringData": { - "username": "VGhpcyBzcGFjZSBpbnRlbnRpb25hbGx5IGxlZnQgYmxhbmsK" - }, - }, - ) - ) - - def test_module_secret_file_contents_double_b64(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join( - self.testdir_v2, "values-secret-v2-file-contents-double-b64.yaml" - ) - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - ret = result.exception.args[0] - self.assertTrue( - len(ret["kubernetes_secret_objects"]) == 1 - and ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "test-secret", - }, - "stringData": { - "username": "VkdocGN5QnpjR0ZqWlNCcGJuUmxiblJwYjI1aGJHeDVJR3hsWm5RZ1lteGhibXNL" - }, - }, - ) - ) - - def test_module_secret_file_contents_binary_b64(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-secret-binary-b64.yaml") - ) - with self.assertRaises(AnsibleExitJson) as result: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - ret = result.exception.args[0] - - # The binary bytes are [ 8, 6, 7, 5, 3, 0, 9 ] (IYKYK) - self.assertTrue( - len(ret["kubernetes_secret_objects"]) == 1 - and ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "secret", - }, - "stringData": {"secret": "CAYHBQMACQ=="}, - }, - ) - ) - - def test_ensure_success_retrieving_block_yaml_policy(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-defaultvp-policy.yaml") - ) - with self.assertRaises(AnsibleExitJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "vault", - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertTrue( - ds_eq( - ret["vault_policies"], - { - "basicPolicy": 'length=10\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\n', # noqa: E501 - "validatedPatternDefaultPolicy": 'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n', # noqa: E501 - }, - ) - ) - - def test_ensure_success_retrieving_block_yaml_value(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-block-yamlstring.yaml") - ) - with self.assertRaises(AnsibleExitJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "vault", - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertTrue( - ds_eq( - ret["parsed_secrets"], - { - "config-demo": DEFAULT_PARSED_SECRET_VALUE - | { - "fields": { - "sshprivkey": "ssh-rsa oNb/kAvwdQl+FKdwzzKo5rnGIB68UOxWoaKPnKdgF/ts67CDBslWGnpUZCpp8TdaxfHmpoyA6nutMwQw8OAMEUybxvilDn+ZVJ/5qgfRBdi8wLKRLTIj0v+ZW7erN9yuZG53xUQAaQjivM3cRyNLIZ9torShYaYwD1UTTDkV97RMfNDlWI5f5FGRvfy429ZfCwbUWUbijrcv/mWc/uO3x/+MBXwa4f8ubzEYlrt4yH/Vbpzs67kE9UJ9z1zurFUFJydy1ZDAdKSiBS91ImI3ccKnbz0lji2bgSYR0Wp1IQhzSpjyJU2rIu9HAEUh85Rwf2jakfLpMcg/hSBer3sG kilroy@example.com", # noqa: E501 - "sshpubkey": "-----BEGIN OPENSSH PRIVATE KEY-----\nTtzxGgWrNerAr1hzUqPW2xphF/Aur1rQXSLv4J7frEJxNED6u/eScsNgwJMGXwRx7QYVohh0ARHVhJdUzJK7pEIphi4BGw==\nwlo+oQsi828b47SKZB8/K9dbeLlLiXh9/hu47MGpeGHZsKbjAdauncuw+YUDDN2EADJjasNMZHjxYhXKtqDjXTIw1X1n0Q==\n-----END OPENSSH PRIVATE KEY-----", # noqa: E501 - }, - "name": "config-demo", - } - }, - ) - ) - - def test_ensure_kubernetes_object_block_yaml_value(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-block-yamlstring.yaml") - ) - with self.assertRaises(AnsibleExitJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertTrue( - ds_eq( - ret["kubernetes_secret_objects"][0], - DEFAULT_KUBERNETES_SECRET_OBJECT - | { - "metadata": DEFAULT_KUBERNETES_METADATA - | { - "name": "config-demo", - }, - "stringData": { - "sshprivkey": "ssh-rsa oNb/kAvwdQl+FKdwzzKo5rnGIB68UOxWoaKPnKdgF/ts67CDBslWGnpUZCpp8TdaxfHmpoyA6nutMwQw8OAMEUybxvilDn+ZVJ/5qgfRBdi8wLKRLTIj0v+ZW7erN9yuZG53xUQAaQjivM3cRyNLIZ9torShYaYwD1UTTDkV97RMfNDlWI5f5FGRvfy429ZfCwbUWUbijrcv/mWc/uO3x/+MBXwa4f8ubzEYlrt4yH/Vbpzs67kE9UJ9z1zurFUFJydy1ZDAdKSiBS91ImI3ccKnbz0lji2bgSYR0Wp1IQhzSpjyJU2rIu9HAEUh85Rwf2jakfLpMcg/hSBer3sG kilroy@example.com", # noqa: E501 - "sshpubkey": "-----BEGIN OPENSSH PRIVATE KEY-----\nTtzxGgWrNerAr1hzUqPW2xphF/Aur1rQXSLv4J7frEJxNED6u/eScsNgwJMGXwRx7QYVohh0ARHVhJdUzJK7pEIphi4BGw==\nwlo+oQsi828b47SKZB8/K9dbeLlLiXh9/hu47MGpeGHZsKbjAdauncuw+YUDDN2EADJjasNMZHjxYhXKtqDjXTIw1X1n0Q==\n-----END OPENSSH PRIVATE KEY-----", # noqa: E501 - }, - }, - ) - ) - - def test_ensure_kubernetes_backend_allowed(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-base-k8s-backend.yaml") - ) - with self.assertRaises(AnsibleExitJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertFalse(ret["failed"]) - - def test_ensure_none_backend_allowed(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-base-none-backend.yaml") - ) - with self.assertRaises(AnsibleExitJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "none", - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertFalse(ret["failed"]) - - def test_ensure_error_conflicting_backends(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-base-k8s-backend.yaml") - ) - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "vault", - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "Secrets file specifies 'kubernetes' backend but pattern config specifies 'vault'." - ) - - def test_ensure_error_unknown_backends(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-base-unknown-backend.yaml") - ) - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "unknown", - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "Currently only the 'vault', 'kubernetes' and 'none' backingStores are supported: unknown" - ) - - def test_ensure_error_secrets_same_name(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-same-secret-names.yaml") - ) - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] == "You cannot have duplicate secret names: ['config-demo']" - ) - - def test_ensure_error_fields_same_name(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-same-field-names.yaml") - ) - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ret["args"][1] == "You cannot have duplicate field names: ['secret']" - - def test_ensure_generate_errors_on_kubernetes(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-generic-onlygenerate.yaml") - ) - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "kubernetes", - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "You cannot have onMissingValue set to 'generate' unless using vault backingstore for secret config-demo field secret" # noqa: E501 - ) - - def test_ensure_generate_errors_on_none_generate(self, getpass): - testfile_output = self.get_file_as_stdout( - os.path.join(self.testdir_v2, "values-secret-v2-generic-onlygenerate.yaml") - ) - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets_plaintext": testfile_output, - "secrets_backing_store": "none", - } - ) - parse_secrets_info.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "You cannot have onMissingValue set to 'generate' unless using vault backingstore for secret config-demo field secret" # noqa: E501 - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/ansible/tests/unit/test_util_datastructures.py b/ansible/tests/unit/test_util_datastructures.py deleted file mode 100644 index 11d7cdae..00000000 --- a/ansible/tests/unit/test_util_datastructures.py +++ /dev/null @@ -1,205 +0,0 @@ -DEFAULT_PARSED_SECRET_VALUE = { - "name": "overwrite-me", - "fields": {}, - "base64": [], - "ini_file": {}, - "generate": [], - "override": [], - "vault_mount": "secret", - "vault_policies": {}, - "vault_prefixes": ["hub"], - "type": "Opaque", - "target_namespaces": [], - "labels": {}, - "annotations": {}, - "paths": {}, -} - -DEFAULT_KUBERNETES_METADATA = { - "name": "overwrite-me", - "labels": {}, - "annotations": {}, - "namespace": "validated-patterns-secrets", -} -DEFAULT_KUBERNETES_SECRET_OBJECT = { - "kind": "Secret", - "type": "Opaque", - "apiVersion": "v1", - "metadata": DEFAULT_KUBERNETES_METADATA, - "stringData": {}, -} - -DEFAULT_VAULT_POLICIES = { - "validatedPatternDefaultPolicy": ( - "length=20\n" - 'rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\n' # noqa: E501 - 'rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\n' # noqa: E501 - 'rule "charset" { charset = "0123456789" min-chars = 1 }\n' - 'rule "charset" { charset = "!@#%^&*" min-chars = 1 }\n' - ), -} - -GENERATE_POLICY_B64_TEST = { - "vault_policies": { - "basicPolicy": 'length=10\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\n', # noqa: E501 - "validatedPatternDefaultPolicy": 'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n', # noqa: E501 - }, - "parsed_secrets": { - "config-demo": { - "annotations": {}, - "base64": ["secret"], - "fields": {"secret": None}, - "generate": ["secret"], - "ini_file": {}, - "labels": {}, - "name": "config-demo", - "namespace": "validated-patterns-secrets", - "override": ["secret"], - "paths": {}, - "type": "Opaque", - "vault_mount": "secret", - "vault_policies": {"secret": "basicPolicy"}, - "vault_prefixes": ["region-one", "snowflake.blueprints.rhecoeng.com"], - } - }, -} - -PARSED_SECRET_VALUE_TEST = { - "parsed_secrets": { - "config-demo": { - "annotations": {}, - "base64": [], - "fields": {"secret": "value123"}, - "generate": [], - "ini_file": {}, - "labels": {}, - "name": "config-demo", - "namespace": "validated-patterns-secrets", - "override": [], - "paths": {}, - "type": "Opaque", - "vault_mount": "secret", - "vault_policies": {}, - "vault_prefixes": ["hub"], - } - }, - "vault_policies": { - "validatedPatternDefaultPolicy": 'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n' # noqa: E501 - }, -} - -PARSED_SECRET_B64_VALUE_TEST = { - "parsed_secrets": { - "config-demo": { - "annotations": {}, - "base64": ["secret"], - "fields": {"secret": "dmFsdWUxMjMK"}, - "generate": [], - "ini_file": {}, - "labels": {}, - "name": "config-demo", - "namespace": "validated-patterns-secrets", - "override": [], - "paths": {}, - "type": "Opaque", - "vault_mount": "secret", - "vault_policies": {}, - "vault_prefixes": ["hub"], - } - }, - "vault_policies": { - "validatedPatternDefaultPolicy": 'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n' # noqa: E501 - }, -} - -PARSED_SECRET_FILE_INJECTION_TEST = { - "parsed_secrets": { - "config-demo": { - "annotations": {}, - "base64": [], - "fields": {"secret": "value123"}, - "generate": [], - "ini_file": {}, - "labels": {}, - "name": "config-demo", - "namespace": "validated-patterns-secrets", - "override": [], - "paths": {}, - "type": "Opaque", - "vault_mount": "secret", - "vault_policies": {}, - "vault_prefixes": [ - "secret/region-one", - "secret/snowflake.blueprints.rhecoeng.com", - ], - }, - "config-demo-file": { - "annotations": {}, - "base64": [], - "fields": {"test": ""}, - "generate": [], - "ini_file": {}, - "labels": {}, - "name": "config-demo-file", - "namespace": "validated-patterns-secrets", - "override": [], - "paths": {"test": "/tmp/footest"}, - "type": "Opaque", - "vault_mount": "secret", - "vault_policies": {}, - "vault_prefixes": [ - "secret/region-two", - "secret/snowflake.blueprints.rhecoeng.com", - ], - }, - }, - "vault_policies": { - "validatedPatternDefaultPolicy": 'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n' # noqa: 501 - }, -} - -PARSED_SECRET_FILE_B64_INJECTION_TEST = { - "parsed_secrets": { - "config-demo": { - "annotations": {}, - "base64": [], - "fields": {"secret": "value123"}, - "generate": [], - "ini_file": {}, - "labels": {}, - "name": "config-demo", - "namespace": "validated-patterns-secrets", - "override": [], - "paths": {}, - "type": "Opaque", - "vault_mount": "secret", - "vault_policies": {}, - "vault_prefixes": [ - "secret/region-one", - "secret/snowflake.blueprints.rhecoeng.com", - ], - }, - "config-demo-file": { - "annotations": {}, - "base64": ["test"], - "fields": {"test": ""}, - "generate": [], - "ini_file": {}, - "labels": {}, - "name": "config-demo-file", - "namespace": "validated-patterns-secrets", - "override": [], - "paths": {"test": "/tmp/footest"}, - "type": "Opaque", - "vault_mount": "secret", - "vault_policies": {}, - "vault_prefixes": [ - "secret/region-two", - "secret/snowflake.blueprints.rhecoeng.com", - ], - }, - }, - "vault_policies": { - "validatedPatternDefaultPolicy": 'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n' # noqa: 501 - }, -} diff --git a/ansible/tests/unit/test_vault_load_parsed_secrets.py b/ansible/tests/unit/test_vault_load_parsed_secrets.py deleted file mode 100644 index 66ec6b69..00000000 --- a/ansible/tests/unit/test_vault_load_parsed_secrets.py +++ /dev/null @@ -1,321 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Simple module to test vault_load_parsed_secrets -""" - -import json -import os -import sys -import unittest -from unittest.mock import call, patch - -import test_util_datastructures -from ansible.module_utils import basic -from ansible.module_utils.common.text.converters import to_bytes - -# TODO(bandini): I could not come up with something better to force the imports to be existing -# when we 'import vault_load_secrets' -sys.path.insert(1, "./ansible/plugins/module_utils") -sys.path.insert(1, "./ansible/plugins/modules") - -import vault_load_parsed_secrets # noqa: E402 - -sys.modules["ansible.modules.vault_load_parsed_secrets"] = vault_load_parsed_secrets - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({"ANSIBLE_MODULE_ARGS": args}) - basic._ANSIBLE_ARGS = to_bytes(args) - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - - pass - - -def exit_json(*args, **kwargs): - """function to patch over exit_json; package return data into an exception""" - if "changed" not in kwargs: - kwargs["changed"] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): - """function to patch over fail_json; package return data into an exception""" - kwargs["failed"] = True - kwargs["args"] = args - raise AnsibleFailJson(kwargs) - - -class TestMyModule(unittest.TestCase): - - def setUp(self): - self.mock_module_helper = patch.multiple( - basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json - ) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.testdir_v2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), "v2") - - def tearDown(self): - return - - def test_module_fail_when_required_args_missing(self): - with self.assertRaises(AnsibleFailJson): - set_module_args({}) - vault_load_parsed_secrets.main() - - # For these tests, we need the data structures that parse_secrets_info outputs. - # Several have been saved in the test_util_datastructures module for this purpose - def test_ensure_value_injection_works(self): - set_module_args( - { - "parsed_secrets": test_util_datastructures.PARSED_SECRET_VALUE_TEST[ - "parsed_secrets" - ], - "vault_policies": test_util_datastructures.PARSED_SECRET_VALUE_TEST[ - "vault_policies" - ], - } - ) - with patch.object( - vault_load_parsed_secrets.VaultSecretLoader, "_run_command" - ) as mock_run_command: - stdout = "" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_parsed_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 2 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='\"'value123'\"'\"", # noqa: E501 - attempts=3, - ), - ] - print(mock_run_command.mock_calls) - mock_run_command.assert_has_calls(calls) - - def test_ensure_b64_value_injection_works(self): - set_module_args( - { - "parsed_secrets": test_util_datastructures.PARSED_SECRET_B64_VALUE_TEST[ - "parsed_secrets" - ], - "vault_policies": test_util_datastructures.PARSED_SECRET_B64_VALUE_TEST[ - "vault_policies" - ], - } - ) - with patch.object( - vault_load_parsed_secrets.VaultSecretLoader, "_run_command" - ) as mock_run_command: - stdout = "" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_parsed_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 2 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='\"'dmFsdWUxMjMK'\"'\"", # noqa: E501 - attempts=3, - ), - ] - print(mock_run_command.mock_calls) - mock_run_command.assert_has_calls(calls) - - def test_ensure_file_injection_works(self): - set_module_args( - { - "parsed_secrets": test_util_datastructures.PARSED_SECRET_FILE_INJECTION_TEST[ - "parsed_secrets" - ], - "vault_policies": test_util_datastructures.PARSED_SECRET_FILE_INJECTION_TEST[ - "vault_policies" - ], - } - ) - with patch.object( - vault_load_parsed_secrets.VaultSecretLoader, "_run_command" - ) as mock_run_command: - stdout = "" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_parsed_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 5 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='\"'value123'\"'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='\"'value123'\"'\"", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/footest' | oc exec -n vault vault-0 -i -- sh -c 'cat - > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv put -mount=secret secret/region-two/config-demo-file test=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/footest' | oc exec -n vault vault-0 -i -- sh -c 'cat - > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo-file test=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - ] - print(mock_run_command.mock_calls) - mock_run_command.assert_has_calls(calls) - - def test_ensure_file_b64_injection_works(self): - set_module_args( - { - "parsed_secrets": test_util_datastructures.PARSED_SECRET_FILE_B64_INJECTION_TEST[ - "parsed_secrets" - ], - "vault_policies": test_util_datastructures.PARSED_SECRET_FILE_B64_INJECTION_TEST[ - "vault_policies" - ], - } - ) - with patch.object( - vault_load_parsed_secrets.VaultSecretLoader, "_run_command" - ) as mock_run_command: - stdout = "" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_parsed_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 5 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='\"'value123'\"'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='\"'value123'\"'\"", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/footest' | oc exec -n vault vault-0 -i -- sh -c 'cat - | base64 --wrap=0> /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv put -mount=secret secret/region-two/config-demo-file test=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/footest' | oc exec -n vault vault-0 -i -- sh -c 'cat - | base64 --wrap=0> /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo-file test=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - ] - print(mock_run_command.mock_calls) - mock_run_command.assert_has_calls(calls) - - def test_ensure_b64_generate_passwords_works(self): - set_module_args( - { - "parsed_secrets": test_util_datastructures.GENERATE_POLICY_B64_TEST[ - "parsed_secrets" - ], - "vault_policies": test_util_datastructures.GENERATE_POLICY_B64_TEST[ - "vault_policies" - ], - } - ) - with patch.object( - vault_load_parsed_secrets.VaultSecretLoader, "_run_command" - ) as mock_run_command: - stdout = "" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_parsed_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 4 - - calls = [ - call( - 'echo \'length=10\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/basicPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/basicPolicy policy=@/tmp/basicPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | base64 --wrap=0 | vault kv put -mount=secret region-one/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | base64 --wrap=0 | vault kv put -mount=secret snowflake.blueprints.rhecoeng.com/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - ] - print(mock_run_command.mock_calls) - mock_run_command.assert_has_calls(calls) - - -if __name__ == "__main__": - unittest.main() diff --git a/ansible/tests/unit/test_vault_load_secrets.py b/ansible/tests/unit/test_vault_load_secrets.py deleted file mode 100644 index 03d25d8c..00000000 --- a/ansible/tests/unit/test_vault_load_secrets.py +++ /dev/null @@ -1,389 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Simple module to test vault_load_secrets -""" - -import json -import os -import sys -import unittest -from unittest.mock import call, patch - -from ansible.module_utils import basic -from ansible.module_utils.common.text.converters import to_bytes - -# TODO(bandini): I could not come up with something better to force the imports to be existing -# when we 'import vault_load_secrets' -sys.path.insert(1, "./ansible/plugins/module_utils") -sys.path.insert(1, "./ansible/plugins/modules") -import load_secrets_common # noqa: E402 - -sys.modules["ansible.module_utils.load_secrets_common"] = load_secrets_common -import load_secrets_v1 # noqa: E402 -import load_secrets_v2 # noqa: E402 - -sys.modules["ansible.module_utils.load_secrets_v1"] = load_secrets_v1 -sys.modules["ansible.module_utils.load_secrets_v2"] = load_secrets_v2 -import vault_load_secrets # noqa: E402 - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({"ANSIBLE_MODULE_ARGS": args}) - basic._ANSIBLE_ARGS = to_bytes(args) - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - - pass - - -def exit_json(*args, **kwargs): - """function to patch over exit_json; package return data into an exception""" - if "changed" not in kwargs: - kwargs["changed"] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): - """function to patch over fail_json; package return data into an exception""" - kwargs["failed"] = True - kwargs["args"] = args - raise AnsibleFailJson(kwargs) - - -class TestMyModule(unittest.TestCase): - - def setUp(self): - self.mock_module_helper = patch.multiple( - basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json - ) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.testdir_v1 = os.path.join(os.path.dirname(os.path.abspath(__file__)), "v1") - self.testfile = open("/tmp/ca.crt", "w") - - def tearDown(self): - self.testfile.close() - try: - os.remove("/tmp/ca.crt") - except OSError: - pass - - def test_module_fail_when_required_args_missing(self): - with self.assertRaises(AnsibleFailJson): - set_module_args({}) - vault_load_secrets.main() - - def test_module_fail_when_values_secret_not_existing(self): - with self.assertRaises(AnsibleExitJson) as ansible_err: - set_module_args( - { - "values_secrets": "/tmp/nonexisting", - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - self.assertEqual(ret["error"], "Missing /tmp/nonexisting file") - self.assertEqual( - ret["msg"], "Values secrets file does not exist: /tmp/nonexisting" - ) - - def test_ensure_empty_files_but_not_secrets_is_ok(self): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v1, - "values-secret-empty-files.yaml", - ) - } - ) - - with patch.object( - load_secrets_v1.LoadSecretsV1, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 2 - - calls = [ - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/config-demo' secret='VALUE'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/aws' access_key_id='VALUE' secret_access_key='VALUE'\"", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_broken_files_fail(self): - for i in ( - "values-secret-broken1.yaml", - "values-secret-broken2.yaml", - "values-secret-broken3.yaml", - ): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args({"values_secrets": os.path.join(self.testdir_v1, i)}) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - - def test_ensure_empty_secrets_but_not_files_is_ok(self): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v1, - "values-secret-empty-secrets.yaml", - ), - } - ) - - with patch.object( - load_secrets_v1.LoadSecretsV1, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 1 - - calls = [ - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'base64 --wrap=0 /tmp/vcontent | vault kv put secret/hub/publickey b64content=- content=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_command_called(self): - set_module_args( - {"values_secrets": os.path.join(self.testdir_v1, "values-secret-good.yaml")} - ) - - with patch.object( - load_secrets_v1.LoadSecretsV1, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 9 - - calls = [ - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/config-demo' secret='demo123'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/googleapi' key='test123'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/cluster_alejandro' name='alejandro' bearerToken='sha256~bumxi-012345678901233455675678678098-abcdef'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/test' s3.accessKey='1234' s3.secretKey='4321' s3Secret='czMuYWNjZXNzS2V5OiAxMjM0CnMzLnNlY3JldEtleTogNDMyMQ=='\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/test2' s3.accessKey='accessKey' s3.secretKey='secretKey' s3Secret='fooo'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/test3' s3.accessKey='aaaaa' s3.secretKey='bbbbbbbb' s3Secret='czMuYWNjZXNzS2V5OiBhYWFhYQpzMy5zZWNyZXRLZXk6IGJiYmJiYmJi'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/region-one/config-demo' secret='region123'\"", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'base64 --wrap=0 /tmp/vcontent | vault kv put secret/hub/cluster_alejandro_ca b64content=- content=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'base64 --wrap=0 /tmp/vcontent | vault kv put secret/region-one/ca b64content=- content=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_good_template_checking(self): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v1, "mcg-values-secret.yaml" - ), - "check_missing_secrets": True, - "values_secret_template": os.path.join( - self.testdir_v1, "template-mcg-working.yaml" - ), - } - ) - with patch.object( - load_secrets_v1.LoadSecretsV1, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 1 - - calls = [ - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/config-demo' secret='VALUE' additionalsecret='test'\"", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_bad_template_checking(self): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v1, "mcg-values-secret.yaml" - ), - "check_missing_secrets": True, - "values_secret_template": os.path.join( - self.testdir_v1, "template-mcg-missing.yaml" - ), - } - ) - with patch.object( - load_secrets_v1.LoadSecretsV1, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr - - with self.assertRaises(AnsibleFailJson) as result: - vault_load_secrets.main() - self.assertTrue(result.exception.args[0]["failed"]) - # In case of failure args[1] contains the msg of the failure - assert ( - result.exception.args[0]["args"][1] - == "Values secret yaml is missing needed secrets from the templates: {'secrets.config-demo.foo'}" - ) - assert mock_run_command.call_count == 0 - - def test_ensure_fqdn_secrets(self): - set_module_args( - {"values_secrets": os.path.join(self.testdir_v1, "values-secret-fqdn.yaml")} - ) - - with patch.object( - load_secrets_v1.LoadSecretsV1, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 3 - - calls = [ - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/hub/test' secret1='foo'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put 'secret/region-one.blueprints.rhecoeng.com/config-demo' secret='region123'\"", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'base64 --wrap=0 /tmp/vcontent | vault kv put secret/region-one/ca b64content=- content=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_check_missing_secrets_errors_out(self): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v1, "mcg-values-secret.yaml" - ), - "check_missing_secrets": True, - "values_secret_template": "", - } - ) - with patch.object( - load_secrets_v1.LoadSecretsV1, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr - - with self.assertRaises(AnsibleFailJson) as result: - vault_load_secrets.main() - self.assertTrue(result.exception.args[0]["failed"]) - # In case of failure args[1] contains the msg of the failure - assert ( - result.exception.args[0]["args"][1] - == "No values_secret_template defined and check_missing_secrets set to True" - ) - assert mock_run_command.call_count == 0 - - -if __name__ == "__main__": - unittest.main() diff --git a/ansible/tests/unit/test_vault_load_secrets_v2.py b/ansible/tests/unit/test_vault_load_secrets_v2.py deleted file mode 100644 index 7b934320..00000000 --- a/ansible/tests/unit/test_vault_load_secrets_v2.py +++ /dev/null @@ -1,761 +0,0 @@ -# Copyright 2022 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Simple module to test vault_load_secrets -""" - -import configparser -import json -import os -import sys -import unittest -from unittest import mock -from unittest.mock import call, patch - -from ansible.module_utils import basic -from ansible.module_utils.common.text.converters import to_bytes - -# TODO(bandini): I could not come up with something better to force the imports to be existing -# when we 'import vault_load_secrets' -sys.path.insert(1, "./ansible/plugins/module_utils") -sys.path.insert(1, "./ansible/plugins/modules") -import load_secrets_common # noqa: E402 - -sys.modules["ansible.module_utils.load_secrets_common"] = load_secrets_common -import load_secrets_v1 # noqa: E402 -import load_secrets_v2 # noqa: E402 - -sys.modules["ansible.module_utils.load_secrets_v1"] = load_secrets_v1 -sys.modules["ansible.module_utils.load_secrets_v2"] = load_secrets_v2 -import vault_load_secrets # noqa: E402 - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({"ANSIBLE_MODULE_ARGS": args}) - basic._ANSIBLE_ARGS = to_bytes(args) - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - - pass - - -def exit_json(*args, **kwargs): - """function to patch over exit_json; package return data into an exception""" - if "changed" not in kwargs: - kwargs["changed"] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): - """function to patch over fail_json; package return data into an exception""" - kwargs["failed"] = True - kwargs["args"] = args - raise AnsibleFailJson(kwargs) - - -@mock.patch("getpass.getpass") -class TestMyModule(unittest.TestCase): - - def create_inifile(self): - self.inifile = open("/tmp/awscredentials", "w") - config = configparser.ConfigParser() - config["default"] = { - "aws_access_key_id": "123123", - "aws_secret_access_key": "abcdefghi", - } - config["foobar"] = { - "aws_access_key_id": "345345", - "aws_secret_access_key": "rstuvwxyz", - } - with self.inifile as configfile: - config.write(configfile) - - def setUp(self): - self.mock_module_helper = patch.multiple( - basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json - ) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.testdir_v2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), "v2") - self.testfile = open("/tmp/ca.crt", "w") - self.create_inifile() - - def tearDown(self): - self.testfile.close() - try: - os.remove("/tmp/ca.crt") - # os.remove("/tmp/awscredentials") - except OSError: - pass - - def test_module_fail_when_required_args_missing(self, getpass): - with self.assertRaises(AnsibleFailJson): - set_module_args({}) - vault_load_secrets.main() - - def test_module_fail_when_values_secret_not_existing(self, getpass): - with self.assertRaises(AnsibleExitJson) as ansible_err: - set_module_args( - { - "values_secrets": "/tmp/nonexisting", - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - self.assertEqual(ret["error"], "Missing /tmp/nonexisting file") - self.assertEqual( - ret["msg"], "Values secrets file does not exist: /tmp/nonexisting" - ) - - def test_ensure_no_vault_policies_is_ok(self, getpass): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-nopolicies.yaml" - ), - } - ) - getpass.return_value = "foo" - with patch.object( - load_secrets_v2.LoadSecretsV2, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 5 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='value123'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='value123'\"", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - | base64 --wrap=0 > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv put -mount=secret secret/region-two/config-demo-file ca_crt=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - | base64 --wrap=0 > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo-file ca_crt=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_policies_are_injected(self, getpass): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-base.yaml" - ), - } - ) - # this will be used for both a secret and a file path - getpass.return_value = "/tmp/ca.crt" - with patch.object( - load_secrets_v2.LoadSecretsV2, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 11 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'echo \'length=10\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/basicPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/basicPolicy policy=@/tmp/basicPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/advancedPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/advancedPolicy policy=@/tmp/advancedPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | vault kv put -mount=secret region-one/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | vault kv put -mount=secret snowflake.blueprints.rhecoeng.com/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv patch -mount=secret region-one/config-demo secret2='/tmp/ca.crt'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv patch -mount=secret snowflake.blueprints.rhecoeng.com/config-demo secret2='/tmp/ca.crt'\"", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv patch -mount=secret region-one/config-demo ca_crt=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv patch -mount=secret snowflake.blueprints.rhecoeng.com/config-demo ca_crt=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - | base64 --wrap=0 > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv patch -mount=secret region-one/config-demo ca_crt2=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - call( - "cat '/tmp/ca.crt' | oc exec -n vault vault-0 -i -- sh -c 'cat - | base64 --wrap=0 > /tmp/vcontent'; oc exec -n vault vault-0 -i -- sh -c 'vault kv patch -mount=secret snowflake.blueprints.rhecoeng.com/config-demo ca_crt2=@/tmp/vcontent; rm /tmp/vcontent'", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_error_wrong_onmissing_value(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-wrong-onmissingvalue.yaml" - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "Secret has vaultPolicy set to nonExisting but no such policy exists" - ) - - def test_ensure_error_wrong_vaultpolicy(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-wrong-vaultpolicy.yaml" - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "Secret has vaultPolicy set to nonExisting but no such policy exists" - ) - - def test_ensure_error_file_wrong_onmissing_value(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, - "values-secret-v2-files-wrong-onmissingvalue.yaml", - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "Secret has onMissingValue set to 'generate' but has a path set" - ) - - def test_ensure_error_file_emptypath(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-files-emptypath.yaml" - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "Secret has onMissingValue set to 'error' and has neither value nor path nor ini_file set" - ) - - def test_ensure_error_file_wrongpath(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-files-wrongpath.yaml" - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ret["args"][1] == "Field has non-existing path: /tmp/nonexisting" - - def test_ensure_error_empty_vaultprefix(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-emptyvaultprefix.yaml" - ), - } - ) - vault_load_secrets.main() - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ret["args"][1] == "Secret config-demo has empty vaultPrefixes" - - def test_ensure_default_no_vaultprefix(self, getpass): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-novaultprefix.yaml" - ), - } - ) - with patch.object( - load_secrets_v2.LoadSecretsV2, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 2 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='value123'\"", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_only_generate_passwords_works(self, getpass): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-onlygenerate.yaml" - ), - } - ) - with patch.object( - load_secrets_v2.LoadSecretsV2, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 7 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'echo \'length=10\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/basicPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/basicPolicy policy=@/tmp/basicPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/advancedPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/advancedPolicy policy=@/tmp/advancedPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | vault kv put -mount=foo region-one/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | vault kv put -mount=foo snowflake.blueprints.rhecoeng.com/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/advancedPolicy/generate | vault kv patch -mount=foo region-one/config-demo secret2=-"', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/advancedPolicy/generate | vault kv patch -mount=foo snowflake.blueprints.rhecoeng.com/config-demo secret2=-"', # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_generate_password_base64_works(self, getpass): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-generate-base64.yaml" - ), - } - ) - with patch.object( - load_secrets_v2.LoadSecretsV2, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 4 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'echo \'length=10\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/basicPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/basicPolicy policy=@/tmp/basicPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | base64 --wrap=0 | vault kv put -mount=secret region-one/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | base64 --wrap=0 | vault kv put -mount=secret snowflake.blueprints.rhecoeng.com/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_error_secrets_same_name(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-same-secret-names.yaml" - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] == "You cannot have duplicate secret names: ['config-demo']" - ) - - def test_ensure_error_fields_same_name(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-same-field-names.yaml" - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ret["args"][1] == "You cannot have duplicate field names: ['secret']" - - def test_password_base64_secret(self, getpass): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-secret-base64.yaml" - ), - } - ) - with patch.object( - load_secrets_v2.LoadSecretsV2, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 2 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret test/config-demo secret='Zm9v'\"", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_error_on_unsupported_backingstore(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, - "values-secret-v2-nonexisting-backingstore.yaml", - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "Currently only the 'vault' backingStore is supported: nonexisting" - ) - - def test_password_default_vp_policy(self, getpass): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-defaultvp-policy.yaml" - ), - } - ) - with patch.object( - load_secrets_v2.LoadSecretsV2, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 6 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'echo \'length=10\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/basicPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/basicPolicy policy=@/tmp/basicPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | vault kv put -mount=secret region-one/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/basicPolicy/generate | vault kv put -mount=secret snowflake.blueprints.rhecoeng.com/config-demo secret=-"', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/validatedPatternDefaultPolicy/generate | vault kv patch -mount=secret region-one/config-demo secret2=-"', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault read -field=password sys/policies/password/validatedPatternDefaultPolicy/generate | vault kv patch -mount=secret snowflake.blueprints.rhecoeng.com/config-demo secret2=-"', # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_error_on_wrong_override(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, - "values-secret-v2-wrong-override.yaml", - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ( - ret["args"][1] - == "'override' attribute requires 'onMissingValue' to be set to 'generate'" - ) - - def test_ensure_override_works(self, getpass): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-test-override.yaml" - ), - } - ) - # this will be used for both a secret and a file path - getpass.return_value = "/tmp/ca.crt" - with patch.object( - load_secrets_v2.LoadSecretsV2, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 5 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'echo \'length=10\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/basicPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/basicPolicy policy=@/tmp/basicPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/advancedPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/advancedPolicy policy=@/tmp/advancedPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault kv get -mount=secret -field=secret region-one/config-demo"', # noqa: E501 - attempts=1, - checkrc=False, - ), - call( - 'oc exec -n vault vault-0 -i -- sh -c "vault kv get -mount=secret -field=secret snowflake.blueprints.rhecoeng.com/config-demo"', # noqa: E501 - attempts=1, - checkrc=False, - ), - ] - mock_run_command.assert_has_calls(calls) - - def test_ensure_error_wrong_ini_file(self, getpass): - with self.assertRaises(AnsibleFailJson) as ansible_err: - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-wrong-ini-file.yaml" - ), - } - ) - vault_load_secrets.main() - - ret = ansible_err.exception.args[0] - self.assertEqual(ret["failed"], True) - assert ret["args"][1] == "ini_file requires at least ini_key to be defined" - - def test_ensure_ini_file_works(self, getpass): - set_module_args( - { - "values_secrets": os.path.join( - self.testdir_v2, "values-secret-v2-ini-file.yaml" - ), - } - ) - with patch.object( - load_secrets_v2.LoadSecretsV2, "_run_command" - ) as mock_run_command: - stdout = "configuration updated" - stderr = "" - ret = 0 - mock_run_command.return_value = ret, stdout, stderr # successful execution - - with self.assertRaises(AnsibleExitJson) as result: - vault_load_secrets.main() - self.assertTrue( - result.exception.args[0]["changed"] - ) # ensure result is changed - assert mock_run_command.call_count == 5 - - calls = [ - call( - 'echo \'length=20\nrule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 }\nrule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 }\nrule "charset" { charset = "0123456789" min-chars = 1 }\nrule "charset" { charset = "!@#%^&*" min-chars = 1 }\n\' | oc exec -n vault vault-0 -i -- sh -c \'cat - > /tmp/validatedPatternDefaultPolicy.hcl\';oc exec -n vault vault-0 -i -- sh -c \'vault write sys/policies/password/validatedPatternDefaultPolicy policy=@/tmp/validatedPatternDefaultPolicy.hcl\'', # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/aws aws_access_key_id='123123'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv patch -mount=secret hub/aws aws_secret_access_key='abcdefghi'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/awsfoobar aws_access_key_id='345345'\"", # noqa: E501 - attempts=3, - ), - call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv patch -mount=secret hub/awsfoobar aws_secret_access_key='rstuvwxyz'\"", # noqa: E501 - attempts=3, - ), - ] - mock_run_command.assert_has_calls(calls) - - -if __name__ == "__main__": - unittest.main() diff --git a/ansible/tests/unit/v1/mcg-values-secret.yaml b/ansible/tests/unit/v1/mcg-values-secret.yaml deleted file mode 100644 index 8586f1a6..00000000 --- a/ansible/tests/unit/v1/mcg-values-secret.yaml +++ /dev/null @@ -1,27 +0,0 @@ ---- -secrets: - # NEVER COMMIT THESE VALUES TO GIT - config-demo: - # Secret used for demonstrating vault storage, external secrets, and ACM distribution - secret: VALUE - additionalsecret: test - - # Required for automated spoke deployment - # aws: - # access_key_id: VALUE - # secret_access_key: VALUE - -# Required for automated spoke deployment -files: - # # ssh-rsa AAA... - # publickey: ~/.ssh/id_rsa.pub - # - # # -----BEGIN RSA PRIVATE KEY - # # ... - # # -----END RSA PRIVATE KEY - # privatekey: ~/.ssh/id_rsa - # - # # {"auths":{"cloud.openshift.com":{"auth":"b3Blb... }}} - # openshiftPullSecret: ~/.dockerconfigjson - # - # azureOsServicePrincipal: ~/osServicePrincipal.json diff --git a/ansible/tests/unit/v1/template-mcg-missing.yaml b/ansible/tests/unit/v1/template-mcg-missing.yaml deleted file mode 100644 index eca36b2e..00000000 --- a/ansible/tests/unit/v1/template-mcg-missing.yaml +++ /dev/null @@ -1,27 +0,0 @@ ---- -secrets: - # NEVER COMMIT THESE VALUES TO GIT - config-demo: - # Secret used for demonstrating vault storage, external secrets, and ACM distribution - secret: VALUE - foo: bar - - # Required for automated spoke deployment - # aws: - # access_key_id: VALUE - # secret_access_key: VALUE - -# Required for automated spoke deployment -files: - # # ssh-rsa AAA... - # publickey: ~/.ssh/id_rsa.pub - # - # # -----BEGIN RSA PRIVATE KEY - # # ... - # # -----END RSA PRIVATE KEY - # privatekey: ~/.ssh/id_rsa - # - # # {"auths":{"cloud.openshift.com":{"auth":"b3Blb... }}} - # openshiftPullSecret: ~/.dockerconfigjson - # - # azureOsServicePrincipal: ~/osServicePrincipal.json diff --git a/ansible/tests/unit/v1/template-mcg-working.yaml b/ansible/tests/unit/v1/template-mcg-working.yaml deleted file mode 100644 index 8445c6f3..00000000 --- a/ansible/tests/unit/v1/template-mcg-working.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -secrets: - # NEVER COMMIT THESE VALUES TO GIT - config-demo: - # Secret used for demonstrating vault storage, external secrets, and ACM distribution - secret: VALUE - - # Required for automated spoke deployment - # aws: - # access_key_id: VALUE - # secret_access_key: VALUE - -# Required for automated spoke deployment -files: - # # ssh-rsa AAA... - # publickey: ~/.ssh/id_rsa.pub - # - # # -----BEGIN RSA PRIVATE KEY - # # ... - # # -----END RSA PRIVATE KEY - # privatekey: ~/.ssh/id_rsa - # - # # {"auths":{"cloud.openshift.com":{"auth":"b3Blb... }}} - # openshiftPullSecret: ~/.dockerconfigjson - # - # azureOsServicePrincipal: ~/osServicePrincipal.json diff --git a/ansible/tests/unit/v1/values-secret-broken1.yaml b/ansible/tests/unit/v1/values-secret-broken1.yaml deleted file mode 100644 index ecfc9df4..00000000 --- a/ansible/tests/unit/v1/values-secret-broken1.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -secrets: - # empty - -files: - # empty diff --git a/ansible/tests/unit/v1/values-secret-broken2.yaml b/ansible/tests/unit/v1/values-secret-broken2.yaml deleted file mode 100644 index 82477acd..00000000 --- a/ansible/tests/unit/v1/values-secret-broken2.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -# secrets: -# empty - -# files: -# empty diff --git a/ansible/tests/unit/v1/values-secret-broken3.yaml b/ansible/tests/unit/v1/values-secret-broken3.yaml deleted file mode 100644 index 6d7295ba..00000000 --- a/ansible/tests/unit/v1/values-secret-broken3.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -secrets: - - borked1 - - borked2 - -files: - foo: - - broken - - broken2 diff --git a/ansible/tests/unit/v1/values-secret-empty-files.yaml b/ansible/tests/unit/v1/values-secret-empty-files.yaml deleted file mode 100644 index 078166a0..00000000 --- a/ansible/tests/unit/v1/values-secret-empty-files.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -secrets: - # NEVER COMMIT THESE VALUES TO GIT - config-demo: - # Secret used for demonstrating vault storage, external secrets, and ACM distribution - secret: VALUE - - # Required for automated spoke deployment - aws: - access_key_id: VALUE - secret_access_key: VALUE - -# Required for automated spoke deployment -files: - # # ssh-rsa AAA... diff --git a/ansible/tests/unit/v1/values-secret-empty-secrets.yaml b/ansible/tests/unit/v1/values-secret-empty-secrets.yaml deleted file mode 100644 index 13739a27..00000000 --- a/ansible/tests/unit/v1/values-secret-empty-secrets.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -secrets: - # NEVER COMMIT THESE VALUES TO GIT - # config-demo: - # # Secret used for demonstrating vault storage, external secrets, and ACM distribution - # secret: VALUE - - # # Required for automated spoke deployment - # aws: - # access_key_id: VALUE - # secret_access_key: VALUE - -# Required for automated spoke deployment -files: - # # ssh-rsa AAA... - publickey: /tmp/ca.crt diff --git a/ansible/tests/unit/v1/values-secret-fqdn.yaml b/ansible/tests/unit/v1/values-secret-fqdn.yaml deleted file mode 100644 index c77496c1..00000000 --- a/ansible/tests/unit/v1/values-secret-fqdn.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -secrets: - test: - secret1: foo - -secrets.region-one.blueprints.rhecoeng.com: - config-demo: - secret: region123 - -files.region-one: - ca: /tmp/ca.crt diff --git a/ansible/tests/unit/v1/values-secret-good.yaml b/ansible/tests/unit/v1/values-secret-good.yaml deleted file mode 100644 index 6db47285..00000000 --- a/ansible/tests/unit/v1/values-secret-good.yaml +++ /dev/null @@ -1,36 +0,0 @@ ---- -secrets: - # NEVER COMMIT THESE VALUES TO GIT - config-demo: - # Secret used for demonstrating vault storage, external secrets, and ACM distribution - secret: demo123 - googleapi: - key: test123 - - cluster_alejandro: - name: alejandro - bearerToken: sha256~bumxi-012345678901233455675678678098-abcdef - - test: - s3.accessKey: "1234" - s3.secretKey: "4321" - - test2: - s3.accessKey: accessKey - s3.secretKey: secretKey - s3Secret: fooo - - test3: - s3.accessKey: "aaaaa" - s3.secretKey: "bbbbbbbb" - -files: - # oc extract -n openshift-config cm/kube-root-ca.crt --to=/home/michele/ --keys=ca.crt - cluster_alejandro_ca: /tmp/ca.crt - -secrets.region-one: - config-demo: - secret: region123 - -files.region-one: - ca: /tmp/ca.crt diff --git a/ansible/tests/unit/v2/aws-example.ini b/ansible/tests/unit/v2/aws-example.ini deleted file mode 100644 index 5e38bfd8..00000000 --- a/ansible/tests/unit/v2/aws-example.ini +++ /dev/null @@ -1,4 +0,0 @@ -; https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html -[default] -aws_access_key_id = A123456789012345678A -aws_secret_access_key = A12345678901234567890123456789012345678A diff --git a/ansible/tests/unit/v2/test-file-contents b/ansible/tests/unit/v2/test-file-contents deleted file mode 100644 index 49c9a88c..00000000 --- a/ansible/tests/unit/v2/test-file-contents +++ /dev/null @@ -1 +0,0 @@ -This space intentionally left blank diff --git a/ansible/tests/unit/v2/test-file-contents.b64 b/ansible/tests/unit/v2/test-file-contents.b64 deleted file mode 100644 index da896ba7..00000000 --- a/ansible/tests/unit/v2/test-file-contents.b64 +++ /dev/null @@ -1 +0,0 @@ -VGhpcyBzcGFjZSBpbnRlbnRpb25hbGx5IGxlZnQgYmxhbmsK \ No newline at end of file diff --git a/ansible/tests/unit/v2/values-secret-v2-base-k8s-backend.yaml b/ansible/tests/unit/v2/values-secret-v2-base-k8s-backend.yaml deleted file mode 100644 index 7194ebc3..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-base-k8s-backend.yaml +++ /dev/null @@ -1,9 +0,0 @@ -version: "2.0" - -backingStore: kubernetes - -secrets: - - name: config-demo - fields: - - name: secret - value: secret diff --git a/ansible/tests/unit/v2/values-secret-v2-base-none-backend.yaml b/ansible/tests/unit/v2/values-secret-v2-base-none-backend.yaml deleted file mode 100644 index 4e1e3cd2..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-base-none-backend.yaml +++ /dev/null @@ -1,11 +0,0 @@ -version: "2.0" - -backingStore: none - -secrets: - - name: config-demo - targetNamespaces: - - default - fields: - - name: secret - value: secret diff --git a/ansible/tests/unit/v2/values-secret-v2-base-unknown-backend.yaml b/ansible/tests/unit/v2/values-secret-v2-base-unknown-backend.yaml deleted file mode 100644 index e1f4c6d5..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-base-unknown-backend.yaml +++ /dev/null @@ -1,9 +0,0 @@ -version: "2.0" - -backingStore: unknown - -secrets: - - name: config-demo - fields: - - name: secret - value: secret diff --git a/ansible/tests/unit/v2/values-secret-v2-base.yaml b/ansible/tests/unit/v2/values-secret-v2-base.yaml deleted file mode 100644 index bf9670d8..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-base.yaml +++ /dev/null @@ -1,38 +0,0 @@ -version: "2.0" - -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#%^&*" min-chars = 1 } - -secrets: - - name: config-demo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - override: true - vaultPolicy: basicPolicy - - name: secret2 - value: null - onMissingValue: prompt - - name: ca_crt - path: /tmp/ca.crt - onMissingValue: error - - name: ca_crt2 - path: null - base64: true - onMissingValue: prompt diff --git a/ansible/tests/unit/v2/values-secret-v2-block-yamlstring.yaml b/ansible/tests/unit/v2/values-secret-v2-block-yamlstring.yaml deleted file mode 100644 index 84165f69..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-block-yamlstring.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: "2.0" - -secrets: - - name: config-demo - fields: - - name: sshprivkey - onMissingValue: error - value: |- - ssh-rsa oNb/kAvwdQl+FKdwzzKo5rnGIB68UOxWoaKPnKdgF/ts67CDBslWGnpUZCpp8TdaxfHmpoyA6nutMwQw8OAMEUybxvilDn+ZVJ/5qgfRBdi8wLKRLTIj0v+ZW7erN9yuZG53xUQAaQjivM3cRyNLIZ9torShYaYwD1UTTDkV97RMfNDlWI5f5FGRvfy429ZfCwbUWUbijrcv/mWc/uO3x/+MBXwa4f8ubzEYlrt4yH/Vbpzs67kE9UJ9z1zurFUFJydy1ZDAdKSiBS91ImI3ccKnbz0lji2bgSYR0Wp1IQhzSpjyJU2rIu9HAEUh85Rwf2jakfLpMcg/hSBer3sG kilroy@example.com - - name: sshpubkey - onMissingValue: error - value: |- - -----BEGIN OPENSSH PRIVATE KEY----- - TtzxGgWrNerAr1hzUqPW2xphF/Aur1rQXSLv4J7frEJxNED6u/eScsNgwJMGXwRx7QYVohh0ARHVhJdUzJK7pEIphi4BGw== - wlo+oQsi828b47SKZB8/K9dbeLlLiXh9/hu47MGpeGHZsKbjAdauncuw+YUDDN2EADJjasNMZHjxYhXKtqDjXTIw1X1n0Q== - -----END OPENSSH PRIVATE KEY----- diff --git a/ansible/tests/unit/v2/values-secret-v2-default-annotations.yaml b/ansible/tests/unit/v2/values-secret-v2-default-annotations.yaml deleted file mode 100644 index af3e2f9b..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-default-annotations.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -version: "2.0" - -annotations: - test-annotation: 42 - -secrets: - - name: test-secret - fields: - - name: username - value: user - - name: password - value: testpass diff --git a/ansible/tests/unit/v2/values-secret-v2-default-labels.yaml b/ansible/tests/unit/v2/values-secret-v2-default-labels.yaml deleted file mode 100644 index 56af6586..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-default-labels.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -version: "2.0" - -defaultLabels: - testlabel: 4 - -secrets: - - name: test-secret - fields: - - name: username - value: user diff --git a/ansible/tests/unit/v2/values-secret-v2-default-namespace.yaml b/ansible/tests/unit/v2/values-secret-v2-default-namespace.yaml deleted file mode 100644 index a0f4db63..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-default-namespace.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -version: "2.0" - -secrets: - test-secret: - fields: - - name: username - value: user diff --git a/ansible/tests/unit/v2/values-secret-v2-defaultvp-policy.yaml b/ansible/tests/unit/v2/values-secret-v2-defaultvp-policy.yaml deleted file mode 100644 index e284d300..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-defaultvp-policy.yaml +++ /dev/null @@ -1,25 +0,0 @@ -version: "2.0" - -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - -secrets: - - name: config-demo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - override: true - vaultPolicy: basicPolicy - - name: secret2 - onMissingValue: generate - override: true - vaultPolicy: validatedPatternDefaultPolicy diff --git a/ansible/tests/unit/v2/values-secret-v2-emptyvaultprefix.yaml b/ansible/tests/unit/v2/values-secret-v2-emptyvaultprefix.yaml deleted file mode 100644 index df1d420a..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-emptyvaultprefix.yaml +++ /dev/null @@ -1,9 +0,0 @@ -version: "2.0" - -secrets: - - name: config-demo - vaultPrefixes: - fields: - - name: secret - value: value123 - onMissingValue: error diff --git a/ansible/tests/unit/v2/values-secret-v2-file-contents-b64.yaml b/ansible/tests/unit/v2/values-secret-v2-file-contents-b64.yaml deleted file mode 100644 index 47ed7219..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-file-contents-b64.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -version: "2.0" - -secrets: - - name: test-secret - fields: - - name: username - path: ~/test-file-contents - base64: true diff --git a/ansible/tests/unit/v2/values-secret-v2-file-contents-double-b64.yaml b/ansible/tests/unit/v2/values-secret-v2-file-contents-double-b64.yaml deleted file mode 100644 index 3a968eca..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-file-contents-double-b64.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -version: "2.0" - -secrets: - - name: test-secret - fields: - - name: username - path: ~/test-file-contents.b64 - base64: true diff --git a/ansible/tests/unit/v2/values-secret-v2-file-contents.yaml b/ansible/tests/unit/v2/values-secret-v2-file-contents.yaml deleted file mode 100644 index e2da90c2..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-file-contents.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -version: "2.0" - -secrets: - - name: test-secret - fields: - - name: username - path: ~/test-file-contents diff --git a/ansible/tests/unit/v2/values-secret-v2-files-emptypath.yaml b/ansible/tests/unit/v2/values-secret-v2-files-emptypath.yaml deleted file mode 100644 index 9c1142aa..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-files-emptypath.yaml +++ /dev/null @@ -1,25 +0,0 @@ -version: "2.0" -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#%^&*" min-chars = 1 } - -secrets: - - name: config-demo - vaultPrefixes: - - secret/region-one - - secret/snowflake.blueprints.rhecoeng.com - fields: - - name: ca_crt - onMissingValue: error diff --git a/ansible/tests/unit/v2/values-secret-v2-files-wrong-onmissingvalue.yaml b/ansible/tests/unit/v2/values-secret-v2-files-wrong-onmissingvalue.yaml deleted file mode 100644 index 36b0e715..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-files-wrong-onmissingvalue.yaml +++ /dev/null @@ -1,26 +0,0 @@ -version: "2.0" -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#%^&*" min-chars = 1 } - -secrets: - - name: config-demo - vaultPrefixes: - - secret/region-one - - secret/snowflake.blueprints.rhecoeng.com - fields: - - name: ca_crt - path: /tmp/ca.crt - onMissingValue: generate diff --git a/ansible/tests/unit/v2/values-secret-v2-files-wrongpath.yaml b/ansible/tests/unit/v2/values-secret-v2-files-wrongpath.yaml deleted file mode 100644 index 35e5cfcf..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-files-wrongpath.yaml +++ /dev/null @@ -1,26 +0,0 @@ -version: "2.0" -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#%^&*" min-chars = 1 } - -secrets: - - name: config-demo - vaultPrefixes: - - secret/region-one - - secret/snowflake.blueprints.rhecoeng.com - fields: - - name: ca_crt - path: /tmp/nonexisting - onMissingValue: error diff --git a/ansible/tests/unit/v2/values-secret-v2-generate-base64.yaml b/ansible/tests/unit/v2/values-secret-v2-generate-base64.yaml deleted file mode 100644 index eed8b402..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-generate-base64.yaml +++ /dev/null @@ -1,21 +0,0 @@ -version: "2.0" -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - -secrets: - - name: config-demo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - base64: true - override: true - vaultPolicy: basicPolicy diff --git a/ansible/tests/unit/v2/values-secret-v2-generic-onlygenerate.yaml b/ansible/tests/unit/v2/values-secret-v2-generic-onlygenerate.yaml deleted file mode 100644 index 46992af1..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-generic-onlygenerate.yaml +++ /dev/null @@ -1,33 +0,0 @@ -version: "2.0" - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#%^&*" min-chars = 1 } - -secrets: - - name: config-demo - targetNamespaces: - - default - vaultMount: foo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - override: true - vaultPolicy: basicPolicy - - name: secret2 - onMissingValue: generate - override: true - vaultPolicy: advancedPolicy diff --git a/ansible/tests/unit/v2/values-secret-v2-ini-file-b64.yaml b/ansible/tests/unit/v2/values-secret-v2-ini-file-b64.yaml deleted file mode 100644 index ff08d20a..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-ini-file-b64.yaml +++ /dev/null @@ -1,23 +0,0 @@ -version: "2.0" -secrets: - - name: aws - fields: - - name: aws_access_key_id - ini_file: '~/aws-example.ini' - ini_section: default - ini_key: aws_access_key_id - - name: aws_secret_access_key - ini_file: '~/aws-example.ini' - ini_key: aws_secret_access_key - - name: awsb64 - fields: - - name: aws_access_key_id - ini_file: '~/aws-example.ini' - ini_section: default - ini_key: aws_access_key_id - base64: true - - name: aws_secret_access_key - ini_file: '~/aws-example.ini' - ini_section: default - ini_key: aws_secret_access_key - base64: true diff --git a/ansible/tests/unit/v2/values-secret-v2-ini-file.yaml b/ansible/tests/unit/v2/values-secret-v2-ini-file.yaml deleted file mode 100644 index c69a1429..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-ini-file.yaml +++ /dev/null @@ -1,21 +0,0 @@ -version: "2.0" -secrets: - - name: aws - fields: - - name: aws_access_key_id - ini_file: /tmp/awscredentials - ini_section: default - ini_key: aws_access_key_id - - name: aws_secret_access_key - ini_file: /tmp/awscredentials - ini_key: aws_secret_access_key - - name: awsfoobar - fields: - - name: aws_access_key_id - ini_file: /tmp/awscredentials - ini_section: foobar - ini_key: aws_access_key_id - - name: aws_secret_access_key - ini_file: /tmp/awscredentials - ini_section: foobar - ini_key: aws_secret_access_key diff --git a/ansible/tests/unit/v2/values-secret-v2-more-namespaces.yaml b/ansible/tests/unit/v2/values-secret-v2-more-namespaces.yaml deleted file mode 100644 index be409af7..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-more-namespaces.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -version: "2.0" - -secrets: - - name: test-secret - targetNamespaces: - - default - - extra - fields: - - name: username - value: user diff --git a/ansible/tests/unit/v2/values-secret-v2-nondefault-namespace.yaml b/ansible/tests/unit/v2/values-secret-v2-nondefault-namespace.yaml deleted file mode 100644 index a0f4db63..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-nondefault-namespace.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -version: "2.0" - -secrets: - test-secret: - fields: - - name: username - value: user diff --git a/ansible/tests/unit/v2/values-secret-v2-none-no-targetnamespaces.yaml b/ansible/tests/unit/v2/values-secret-v2-none-no-targetnamespaces.yaml deleted file mode 100644 index 2a5ef0b6..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-none-no-targetnamespaces.yaml +++ /dev/null @@ -1,33 +0,0 @@ -version: "2.0" - -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#%^&*" min-chars = 1 } - -secrets: - - name: config-demo - vaultMount: foo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - override: true - vaultPolicy: basicPolicy - - name: secret2 - onMissingValue: generate - override: true - vaultPolicy: advancedPolicy diff --git a/ansible/tests/unit/v2/values-secret-v2-nonexisting-backingstore.yaml b/ansible/tests/unit/v2/values-secret-v2-nonexisting-backingstore.yaml deleted file mode 100644 index 906e3167..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-nonexisting-backingstore.yaml +++ /dev/null @@ -1,23 +0,0 @@ -version: "2.0" - -backingStore: nonexisting - -secrets: - - name: config-demo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - vaultPolicy: basicPolicy - - name: secret2 - value: null - onMissingValue: prompt - - name: ca_crt - path: /tmp/ca.crt - onMissingValue: error - - name: ca_crt2 - path: null - base64: true - onMissingValue: prompt diff --git a/ansible/tests/unit/v2/values-secret-v2-nopolicies.yaml b/ansible/tests/unit/v2/values-secret-v2-nopolicies.yaml deleted file mode 100644 index 3b465700..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-nopolicies.yaml +++ /dev/null @@ -1,24 +0,0 @@ -version: "2.0" - -backingStore: vault - -secrets: - - name: config-demo - vaultPrefixes: - - secret/region-one - - secret/snowflake.blueprints.rhecoeng.com - fields: - - name: secret - value: value123 - onMissingValue: error - - - name: config-demo-file - vaultPrefixes: - - secret/region-two - - secret/snowflake.blueprints.rhecoeng.com - - fields: - - name: ca_crt - path: /tmp/ca.crt - base64: true - onMissingValue: error diff --git a/ansible/tests/unit/v2/values-secret-v2-novaultprefix.yaml b/ansible/tests/unit/v2/values-secret-v2-novaultprefix.yaml deleted file mode 100644 index 92449dae..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-novaultprefix.yaml +++ /dev/null @@ -1,8 +0,0 @@ -version: "2.0" - -secrets: - - name: config-demo - fields: - - name: secret - value: value123 - onMissingValue: error diff --git a/ansible/tests/unit/v2/values-secret-v2-onlygenerate.yaml b/ansible/tests/unit/v2/values-secret-v2-onlygenerate.yaml deleted file mode 100644 index 2a5ef0b6..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-onlygenerate.yaml +++ /dev/null @@ -1,33 +0,0 @@ -version: "2.0" - -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#%^&*" min-chars = 1 } - -secrets: - - name: config-demo - vaultMount: foo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - override: true - vaultPolicy: basicPolicy - - name: secret2 - onMissingValue: generate - override: true - vaultPolicy: advancedPolicy diff --git a/ansible/tests/unit/v2/values-secret-v2-override-labels.yaml b/ansible/tests/unit/v2/values-secret-v2-override-labels.yaml deleted file mode 100644 index 13a460be..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-override-labels.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -version: "2.0" - -defaultLabels: - testlabel: 4 - -secrets: - - name: test-secret - labels: - overridelabel: 42 - fields: - - name: username - value: user diff --git a/ansible/tests/unit/v2/values-secret-v2-override-namespace.yaml b/ansible/tests/unit/v2/values-secret-v2-override-namespace.yaml deleted file mode 100644 index ad53cf77..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-override-namespace.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -version: "2.0" - -secretStoreNamespace: 'overridden-namespace' - -secrets: - - name: test-secret - fields: - - name: username - value: user diff --git a/ansible/tests/unit/v2/values-secret-v2-override-type-none.yaml b/ansible/tests/unit/v2/values-secret-v2-override-type-none.yaml deleted file mode 100644 index 1d110671..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-override-type-none.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -version: "2.0" - -# This is the actual default -defaultNamespace: 'validated-patterns-secrets' - -secrets: - - name: test-secret - type: 'user-specified' - targetNamespaces: - - default - fields: - - name: username - value: user diff --git a/ansible/tests/unit/v2/values-secret-v2-override-type.yaml b/ansible/tests/unit/v2/values-secret-v2-override-type.yaml deleted file mode 100644 index 1bf8e369..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-override-type.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -version: "2.0" - -# This is the actual default -defaultNamespace: 'validated-patterns-secrets' - -secrets: - - name: test-secret - type: 'user-specified' - fields: - - name: username - value: user diff --git a/ansible/tests/unit/v2/values-secret-v2-same-field-names.yaml b/ansible/tests/unit/v2/values-secret-v2-same-field-names.yaml deleted file mode 100644 index 4845e269..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-same-field-names.yaml +++ /dev/null @@ -1,14 +0,0 @@ -version: "2.0" - -secrets: - - name: config-demo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - value: foo - onMissingValue: error - - name: secret - value: bar - onMissingValue: prompt diff --git a/ansible/tests/unit/v2/values-secret-v2-same-secret-names.yaml b/ansible/tests/unit/v2/values-secret-v2-same-secret-names.yaml deleted file mode 100644 index 3e17e536..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-same-secret-names.yaml +++ /dev/null @@ -1,20 +0,0 @@ -version: "2.0" - -secrets: - - name: config-demo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - value: foo - onMissingValue: error - - - name: config-demo - vaultPrefixes: - - region-two - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret2 - value: bar - onMissingValue: prompt diff --git a/ansible/tests/unit/v2/values-secret-v2-secret-base64.yaml b/ansible/tests/unit/v2/values-secret-v2-secret-base64.yaml deleted file mode 100644 index b361b34d..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-secret-base64.yaml +++ /dev/null @@ -1,11 +0,0 @@ -version: "2.0" - -secrets: - - name: config-demo - vaultPrefixes: - - test - fields: - - name: secret - value: foo - onMissingValue: error - base64: true diff --git a/ansible/tests/unit/v2/values-secret-v2-secret-binary-b64.yaml b/ansible/tests/unit/v2/values-secret-v2-secret-binary-b64.yaml deleted file mode 100644 index 579c7d6e..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-secret-binary-b64.yaml +++ /dev/null @@ -1,10 +0,0 @@ -version: "2.0" - -secrets: - - name: secret - fields: - - name: secret - # Should contain 8, 6, 7, 5, 3, 0, 9 in binary - path: '/tmp/testbinfile.bin' - onMissingValue: error - base64: true diff --git a/ansible/tests/unit/v2/values-secret-v2-test-override.yaml b/ansible/tests/unit/v2/values-secret-v2-test-override.yaml deleted file mode 100644 index 8efdd95c..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-test-override.yaml +++ /dev/null @@ -1,28 +0,0 @@ -version: "2.0" - -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#%^&*" min-chars = 1 } - -secrets: - - name: config-demo - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - override: false - vaultPolicy: basicPolicy diff --git a/ansible/tests/unit/v2/values-secret-v2-wrong-ini-file.yaml b/ansible/tests/unit/v2/values-secret-v2-wrong-ini-file.yaml deleted file mode 100644 index fb9b253c..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-wrong-ini-file.yaml +++ /dev/null @@ -1,9 +0,0 @@ -version: "2.0" -secrets: - - name: aws - fields: - - name: aws_key_id - ini_file: ~/.aws/credentials - ini_section: default - # The below is required - # ini_key: aws_access_key_id diff --git a/ansible/tests/unit/v2/values-secret-v2-wrong-onmissingvalue.yaml b/ansible/tests/unit/v2/values-secret-v2-wrong-onmissingvalue.yaml deleted file mode 100644 index 2d53807e..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-wrong-onmissingvalue.yaml +++ /dev/null @@ -1,20 +0,0 @@ -version: "2.0" - -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - -secrets: - - name: config-demo - vaultPrefixes: - - secret/region-one - - secret/snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - vaultPolicy: nonExisting diff --git a/ansible/tests/unit/v2/values-secret-v2-wrong-override.yaml b/ansible/tests/unit/v2/values-secret-v2-wrong-override.yaml deleted file mode 100644 index 650e93b5..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-wrong-override.yaml +++ /dev/null @@ -1,11 +0,0 @@ -version: "2.0" - -secrets: - - name: config-demo - vaultPrefixes: - - region-one - fields: - - name: secret - value: null - onMissingValue: prompt - override: true diff --git a/ansible/tests/unit/v2/values-secret-v2-wrong-vaultpolicy.yaml b/ansible/tests/unit/v2/values-secret-v2-wrong-vaultpolicy.yaml deleted file mode 100644 index 2d53807e..00000000 --- a/ansible/tests/unit/v2/values-secret-v2-wrong-vaultpolicy.yaml +++ /dev/null @@ -1,20 +0,0 @@ -version: "2.0" - -backingStore: vault - -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - -secrets: - - name: config-demo - vaultPrefixes: - - secret/region-one - - secret/snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - vaultPolicy: nonExisting diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 00000000..cb11ca24 --- /dev/null +++ b/requirements.yml @@ -0,0 +1,4 @@ +--- +# Define Ansible collection requirements here +collections: + - name: git+https://github.com/validatedpatterns/rhvp.cluster_utils.git,v1 diff --git a/scripts/display-secrets-info.sh b/scripts/display-secrets-info.sh index 124a3454..73806971 100755 --- a/scripts/display-secrets-info.sh +++ b/scripts/display-secrets-info.sh @@ -27,4 +27,4 @@ fi PATTERN_NAME=$(basename "`pwd`") -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" -e override_no_log=false "${PLAYBOOKPATH}/process_secrets/display_secrets_info.yml" +ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" -e override_no_log=false "rhvp.cluster_utils.display_secrets_info" From 0b3ac1e603c2396b7545a13e3d0b2e52e96c9732 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Mon, 16 Sep 2024 10:20:39 -0500 Subject: [PATCH 179/222] Make adjustments for ansible code moving into separate collection repo --- .github/linters/.gitleaks.toml | 6 +-- .github/workflows/ansible-lint.yml | 17 --------- .github/workflows/ansible-unittest.yml | 52 -------------------------- scripts/display-secrets-info.sh | 4 -- scripts/load-k8s-secrets.sh | 5 +-- scripts/process-secrets.sh | 5 +-- scripts/vault-utils.sh | 5 +-- scripts/write-token-kubeconfig.sh | 5 +-- 8 files changed, 5 insertions(+), 94 deletions(-) delete mode 100644 .github/workflows/ansible-lint.yml delete mode 100644 .github/workflows/ansible-unittest.yml diff --git a/.github/linters/.gitleaks.toml b/.github/linters/.gitleaks.toml index b80cdc04..9ad74347 100644 --- a/.github/linters/.gitleaks.toml +++ b/.github/linters/.gitleaks.toml @@ -1,8 +1,4 @@ [whitelist] # As of v4, gitleaks only matches against filename, not path in the # files directive. Leaving content for backwards compatibility. -files = [ - "ansible/plugins/modules/*.py", - "ansible/tests/unit/test_*.py", - "ansible/tests/unit/v1/*.yaml", -] +files = [ ] diff --git a/.github/workflows/ansible-lint.yml b/.github/workflows/ansible-lint.yml deleted file mode 100644 index c2b2981b..00000000 --- a/.github/workflows/ansible-lint.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Ansible Lint # feel free to pick your own name - -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - # Important: This sets up your GITHUB_WORKSPACE environment variable - - uses: actions/checkout@v4 - - - name: Lint Ansible Playbook - uses: ansible/ansible-lint-action@v6 - # Let's point it to the path - with: - path: "ansible/" diff --git a/.github/workflows/ansible-unittest.yml b/.github/workflows/ansible-unittest.yml deleted file mode 100644 index c9f7485a..00000000 --- a/.github/workflows/ansible-unittest.yml +++ /dev/null @@ -1,52 +0,0 @@ ---- -name: Ansible unit tests - -# -# Documentation: -# https://help.github.com/en/articles/workflow-syntax-for-github-actions -# - -############################# -# Start the job on all push # -############################# -on: [push, pull_request] - -############### -# Set the Job # -############### -jobs: - ansible_unittests: - # Name the Job - name: Ansible unit tests - strategy: - matrix: - python-version: [3.11.3] - # Set the agent to run on - runs-on: ubuntu-latest - - ################## - # Load all steps # - ################## - steps: - ########################## - # Checkout the code base # - ########################## - - name: Checkout Code - uses: actions/checkout@v4 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pytest ansible - - - name: Run make ansible-unittest - run: | - make ansible-unittest diff --git a/scripts/display-secrets-info.sh b/scripts/display-secrets-info.sh index 73806971..d9915855 100755 --- a/scripts/display-secrets-info.sh +++ b/scripts/display-secrets-info.sh @@ -10,10 +10,6 @@ SCRIPT=$(get_abs_filename "$0") SCRIPTPATH=$(dirname "${SCRIPT}") COMMONPATH=$(dirname "${SCRIPTPATH}") PATTERNPATH=$(dirname "${COMMONPATH}") -ANSIBLEPATH="$(dirname ${SCRIPTPATH})/ansible" -PLAYBOOKPATH="${ANSIBLEPATH}/playbooks" - -export ANSIBLE_CONFIG="${ANSIBLEPATH}/ansible.cfg" if [ "$#" -ge 1 ]; then export VALUES_SECRET=$(get_abs_filename "${1}") diff --git a/scripts/load-k8s-secrets.sh b/scripts/load-k8s-secrets.sh index 33c2f9a5..9219f92f 100755 --- a/scripts/load-k8s-secrets.sh +++ b/scripts/load-k8s-secrets.sh @@ -10,10 +10,7 @@ SCRIPT=$(get_abs_filename "$0") SCRIPTPATH=$(dirname "${SCRIPT}") COMMONPATH=$(dirname "${SCRIPTPATH}") PATTERNPATH=$(dirname "${COMMONPATH}") -ANSIBLEPATH="$(dirname ${SCRIPTPATH})/ansible" -PLAYBOOKPATH="${ANSIBLEPATH}/playbooks" -export ANSIBLE_CONFIG="${ANSIBLEPATH}/ansible.cfg" PATTERN_NAME=${1:-$(basename "`pwd`")} -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "${PLAYBOOKPATH}/k8s_secrets/k8s_secrets.yml" +ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "rhvp.cluster_utils.k8s_secrets" diff --git a/scripts/process-secrets.sh b/scripts/process-secrets.sh index 509d6d71..47eff7fa 100755 --- a/scripts/process-secrets.sh +++ b/scripts/process-secrets.sh @@ -10,11 +10,8 @@ SCRIPT=$(get_abs_filename "$0") SCRIPTPATH=$(dirname "${SCRIPT}") COMMONPATH=$(dirname "${SCRIPTPATH}") PATTERNPATH=$(dirname "${COMMONPATH}") -ANSIBLEPATH="$(dirname ${SCRIPTPATH})/ansible" -PLAYBOOKPATH="${ANSIBLEPATH}/playbooks" -export ANSIBLE_CONFIG="${ANSIBLEPATH}/ansible.cfg" PATTERN_NAME=${1:-$(basename "`pwd`")} SECRETS_BACKING_STORE="$($SCRIPTPATH/determine-secretstore-backend.sh)" -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" "${PLAYBOOKPATH}/process_secrets/process_secrets.yml" +ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" "rhvp.cluster_utils.process_secrets" diff --git a/scripts/vault-utils.sh b/scripts/vault-utils.sh index 310d76d6..b014e5a4 100755 --- a/scripts/vault-utils.sh +++ b/scripts/vault-utils.sh @@ -10,9 +10,6 @@ SCRIPT=$(get_abs_filename "$0") SCRIPTPATH=$(dirname "${SCRIPT}") COMMONPATH=$(dirname "${SCRIPTPATH}") PATTERNPATH=$(dirname "${COMMONPATH}") -ANSIBLEPATH="$(dirname ${SCRIPTPATH})/ansible" -PLAYBOOKPATH="${ANSIBLEPATH}/playbooks" -export ANSIBLE_CONFIG="${ANSIBLEPATH}/ansible.cfg" # Parse arguments if [ $# -lt 1 ]; then @@ -28,4 +25,4 @@ if [ -z ${TASK} ]; then exit 1 fi -ansible-playbook -t "${TASK}" -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "${PLAYBOOKPATH}/vault/vault.yaml" +ansible-playbook -t "${TASK}" -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "rhvp.cluster_utils.vault" diff --git a/scripts/write-token-kubeconfig.sh b/scripts/write-token-kubeconfig.sh index 12a2bb80..7544fac2 100755 --- a/scripts/write-token-kubeconfig.sh +++ b/scripts/write-token-kubeconfig.sh @@ -12,8 +12,5 @@ SCRIPT=$(get_abs_filename "$0") SCRIPTPATH=$(dirname "${SCRIPT}") COMMONPATH=$(dirname "${SCRIPTPATH}") PATTERNPATH=$(dirname "${COMMONPATH}") -ANSIBLEPATH="$(dirname ${SCRIPTPATH})/ansible" -PLAYBOOKPATH="${ANSIBLEPATH}/playbooks" -export ANSIBLE_CONFIG="${ANSIBLEPATH}/ansible.cfg" -ansible-playbook -e pattern_dir="${PATTERNPATH}" -e kubeconfig_file="${OUTPUTFILE}" "${PLAYBOOKPATH}/write-token-kubeconfig/write-token-kubeconfig.yml" +ansible-playbook -e pattern_dir="${PATTERNPATH}" -e kubeconfig_file="${OUTPUTFILE}" "rhvp.cluster_utils.write-token-kubeconfig" From 08cff4fedf824cc2b34a78c2f8395f124a78fe4d Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 17 Sep 2024 10:53:07 +0200 Subject: [PATCH 180/222] Allow customizing the clusterGroupChartVersion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ❯ helm template . --show-only "templates/pattern.yaml" --- apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 kind: Pattern metadata: name: release-name namespace: openshift-operators spec: clusterGroupName: default gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main multiSourceConfig: enabled: false ❯ helm template . --show-only "templates/pattern.yaml" --set main.multiSourceConfig.clusterGroupChartVersion=0.9.\* --- apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 kind: Pattern metadata: name: release-name namespace: openshift-operators spec: clusterGroupName: default gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main multiSourceConfig: enabled: false clusterGroupChartVersion: 0.9.* --- operator-install/templates/pattern.yaml | 3 +++ operator-install/values.yaml | 1 + 2 files changed, 4 insertions(+) diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index 3eda9482..072036ee 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -20,6 +20,9 @@ spec: {{- if .Values.main.multiSourceConfig.helmRepoUrl }} helmRepoUrl: {{ .Values.main.multiSourceConfig.helmRepoUrl }} {{- end }} {{/* if .Values.main.multiSourceConfig.helmRepoUrl */}} +{{- if .Values.main.multiSourceConfig.clusterGroupChartVersion }} + clusterGroupChartVersion: {{ .Values.main.multiSourceConfig.clusterGroupChartVersion }} +{{- end }} {{/* if .Values.main.multiSourceConfig.clusterGroupChartVersion */}} {{- if .Values.main.analyticsUUID }} analyticsUUID: {{ .Values.main.analyticsUUID }} {{- end }} {{/* if .Values.main.analyticsUUID */}} diff --git a/operator-install/values.yaml b/operator-install/values.yaml index 62c9943a..f9b81abd 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -18,6 +18,7 @@ main: multiSourceConfig: enabled: false # helmRepoUrl: registry.internal.network/helm + # clusterGroupChartVersion: 0.8.* # String to enable certain experimental capabilities in the operator and the # framework. Not needed unless you know exactly what you're doing. From 003e0118f0977a2c30d866f19348b8ece91ef0ff Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 17 Sep 2024 10:53:39 +0200 Subject: [PATCH 181/222] Release pattern-install v0.0.2 --- operator-install/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operator-install/Chart.yaml b/operator-install/Chart.yaml index 74adcf8f..5122abea 100644 --- a/operator-install/Chart.yaml +++ b/operator-install/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to build and deploy a Cloud Pattern via the patterns o keywords: - pattern name: pattern-install -version: 0.0.1 +version: 0.0.2 From 333152792a413f8032eae0586502e7af8e9f9df5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 17 Sep 2024 10:54:14 +0200 Subject: [PATCH 182/222] Drop the chart splitting workflows They used to run only for the main branch and this is the v1 branch, but let's drop them anyway as they cause quite a bit of confusion. --- .github/workflows/chart-branches.yml | 126 --------------------------- .github/workflows/chart-split.yml | 42 --------- 2 files changed, 168 deletions(-) delete mode 100644 .github/workflows/chart-branches.yml delete mode 100644 .github/workflows/chart-split.yml diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml deleted file mode 100644 index 5ec0ce8f..00000000 --- a/.github/workflows/chart-branches.yml +++ /dev/null @@ -1,126 +0,0 @@ ---- -name: Create per-chart branches - -# We only run this job on the charts that will be later moved to full blown charts -# We also want to run the subtree comand only for the charts that have been actually changed -# because git subtree split is a bit of an expensive operation -# github actions do not support yaml anchors so there is more duplication than usual -on: - push: - branches: - - main - paths: - - 'acm/**' - - 'golang-external-secrets/**' - - 'hashicorp-vault/**' - - 'letsencrypt/**' - - 'clustergroup/**' - - 'operator-install/**' - -jobs: - changes: - name: Figure out per-chart changes - if: github.repository == 'validatedpatterns/common' - runs-on: ubuntu-latest - permissions: read-all - outputs: - acm: ${{ steps.filter.outputs.acm }} - golang-external-secrets: ${{ steps.filter.outputs.golang-external-secrets }} - hashicorp-vault: ${{ steps.filter.outputs.hashicorp-vault }} - letsencrypt: ${{ steps.filter.outputs.letsencrypt }} - clustergroup: ${{ steps.filter.outputs.clustergroup }} - operator-install: ${{ steps.filter.outputs.operator-install }} - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - uses: dorny/paths-filter@v3 - id: filter - with: - filters: | - acm: - - 'acm/**' - golang-external-secrets: - - 'golang-external-secrets/**' - hashicorp-vault: - - 'hashicorp-vault/**' - letsencrypt: - - 'letsencrypt/**' - clustergroup: - - 'clustergroup/**' - operator-install: - - 'operator-install/**' - - acm: - needs: changes - if: ${{ (needs.changes.outputs.acm == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: acm - target_repository: validatedpatterns/acm-chart - secrets: inherit - - golang-external-secrets: - needs: changes - if: ${{ (needs.changes.outputs.golang-external-secrets == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: golang-external-secrets - target_repository: validatedpatterns/golang-external-secrets-chart - secrets: inherit - - hashicorp-vault: - needs: changes - if: ${{ (needs.changes.outputs.hashicorp-vault == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: hashicorp-vault - target_repository: validatedpatterns/hashicorp-vault-chart - secrets: inherit - - letsencrypt: - needs: changes - if: ${{ (needs.changes.outputs.letsencrypt == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: letsencrypt - target_repository: validatedpatterns/letsencrypt-chart - secrets: inherit - - clustergroup: - needs: changes - if: ${{ (needs.changes.outputs.clustergroup == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - chart_name: clustergroup - target_repository: validatedpatterns/clustergroup-chart - secrets: inherit - - # The folder is named 'operator-install' but the chart is called 'pattern-install' - operator-install: - needs: changes - if: ${{ (needs.changes.outputs.operator-install == 'true') && (github.repository == 'validatedpatterns/common') }} - uses: validatedpatterns/common/.github/workflows/chart-split.yml@main - permissions: - actions: write - contents: write - with: - # The name here is really the folder to be used for the chart - chart_name: operator-install - target_repository: validatedpatterns/pattern-install-chart - secrets: inherit diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml deleted file mode 100644 index 150e419b..00000000 --- a/.github/workflows/chart-split.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -name: Split into chart repo branches - -on: - workflow_call: - inputs: - chart_name: - required: true - type: string - target_repository: - required: true - type: string - -jobs: - split_chart: - runs-on: ubuntu-latest - permissions: - actions: write - contents: write - steps: - - name: Checkout Code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ secrets.CHARTS_REPOS_TOKEN }} - - - name: Run git subtree split and push - env: - GITHUB_TOKEN: ${{ secrets.CHARTS_REPOS_TOKEN }} - run: | - set -e - N="${{ inputs.chart_name }}" - B="${N}-main-single-chart" - GITIMG="quay.io/hybridcloudpatterns/gitsubtree-container:2.40.1" - sudo apt-get update -y && sudo apt-get install -y podman - echo "Running subtree split for ${B}" - podman pull "${GITIMG}" - git push origin -d "${B}" || /bin/true - # Git subtree got broken on recent versions of git hence this container - podman run --net=host --rm -t -v .:/git "${GITIMG}" subtree split -P "${N}" -b "${B}" - #git clone https://validatedpatterns:${GITHUB_TOKEN}@github.com/validatedpatterns/common.git -b "acm-main-single-chart" --single-branch - git push --force https://validatedpatterns:"${GITHUB_TOKEN}"@github.com/${{ inputs.target_repository }}.git "${B}:main" From 0123cdebec0e5579472fab388b7a9790f5b34c7a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 18 Sep 2024 09:07:52 +0200 Subject: [PATCH 183/222] Make sure we compare lists with lists when doing a difference While this works with older ansible versions (2.15 and before), we need to check the difference between two lists and not a list and an item. This breaks with ansible 2.16 and onwards Tested with newer ansible and the vault now unseals correctly. --- ansible/roles/vault_utils/tasks/vault_status.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansible/roles/vault_utils/tasks/vault_status.yaml b/ansible/roles/vault_utils/tasks/vault_status.yaml index 9dc3e426..a915db02 100644 --- a/ansible/roles/vault_utils/tasks/vault_status.yaml +++ b/ansible/roles/vault_utils/tasks/vault_status.yaml @@ -58,4 +58,4 @@ - name: "Followers" ansible.builtin.set_fact: - followers: "{{ vault_pods | difference(vault_pod) }}" + followers: "{{ vault_pods | difference([vault_pod]) }}" From 3064c777e7ae304629054fc66c9e5b6243b62bac Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 24 Sep 2024 08:42:03 +0200 Subject: [PATCH 184/222] Add a note about the changes in common --- Changes.md | 4 ++++ README.md | 24 +++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Changes.md b/Changes.md index e37359b7..c12f1755 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,9 @@ # Changes +## Sep 24, 2024 + +* Ansible has been moved out of the common code tree, you must use a clustergroup chart that is >= 0.9.1 + ## Sep 6, 2024 * Most charts have been removed from the tree. To get the charts you now have to point to them diff --git a/README.md b/README.md index 3cb34b0a..41223529 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,29 @@ This is the `main` branch of common and it assumes that the pattern is fully multisource (meaning that any used charts from VP is actually referenced from either a helm chart repository or quay repository). I.e. there are no helm -charts contained in this branch of common. +charts contained in this branch of common and there is no ansible code neither. + +The helm charts now live in separate repositories under the VP +[organization](https://github.com/validatedpatterns) on GitHub. The repositories are: + +- clustergroup-chart +- pattern-install-chart +- hashicorp-vault-chart +- golang-external-secrets-chart +- acm-chart +- letsencrypt-chart + +The ansible bits live in this [repository](https://github.com/validatedpatterns/rhvp.cluster_utils) + +In order to be able to use this "slimmed-down" main branch of common you *must* +use a 0.9.* clustergroup-chart that. Add the following to your `values-global.yaml`: + +```yaml +main: + multiSourceConfig: + enabled: true + clusterGroupChartVersion: 0.9.* +``` ## Start Here From 27d4919f14aa429d041240a46a2422355e82494e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 25 Sep 2024 19:01:10 +0200 Subject: [PATCH 185/222] Add qe-tests target --- Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Makefile b/Makefile index ce4a4a91..350dc099 100644 --- a/Makefile +++ b/Makefile @@ -230,6 +230,14 @@ test: ## run helm tests helmlint: ## run helm lint @for t in $(CHARTS); do common/scripts/lint.sh $$t $(TEST_OPTS); if [ $$? != 0 ]; then exit 1; fi; done +.PHONY: qe-tests +qe-tests: ## Runs the tests that QE runs + @set -e; if [ -f ./tests/interop/run_tests.sh ]; then \ + ./tests/interop/run_tests.sh; \ + else \ + echo "No ./tests/interop/run_tests.sh found skipping"; \ + fi + API_URL ?= https://raw.githubusercontent.com/hybrid-cloud-patterns/ocp-schemas/main/openshift/4.10/ KUBECONFORM_SKIP ?= -skip 'CustomResourceDefinition,ClusterIssuer,CertManager,Certificate,ArgoCD' From dbc4cea3e2ed78998ccf9545d2d9e7b9aca386fe Mon Sep 17 00:00:00 2001 From: Andrew Beekhof Date: Thu, 26 Sep 2024 09:32:58 +1000 Subject: [PATCH 186/222] Remove assorted detritus --- examples/blank/Chart.yaml | 6 - examples/blank/templates/manifest.yaml | 4 - examples/blank/values.yaml | 2 - examples/industrial-edge-factory.yaml | 112 -------- examples/industrial-edge-hub.yaml | 241 ------------------ examples/kustomize-renderer/Chart.yaml | 6 - examples/kustomize-renderer/environment.yaml | 34 --- .../kustomize-renderer/kustomization.yaml | 5 - examples/kustomize-renderer/kustomize | 14 - .../templates/environment.yaml | 34 --- examples/kustomize-renderer/values.yaml | 12 - examples/medical-diagnosis-hub.yaml | 228 ----------------- examples/secrets/values-secret.v1.yaml | 33 --- examples/secrets/values-secret.v2.yaml | 114 --------- examples/values-example.yaml | 207 --------------- values-global.yaml | 20 -- 16 files changed, 1072 deletions(-) delete mode 100644 examples/blank/Chart.yaml delete mode 100644 examples/blank/templates/manifest.yaml delete mode 100644 examples/blank/values.yaml delete mode 100644 examples/industrial-edge-factory.yaml delete mode 100644 examples/industrial-edge-hub.yaml delete mode 100644 examples/kustomize-renderer/Chart.yaml delete mode 100644 examples/kustomize-renderer/environment.yaml delete mode 100644 examples/kustomize-renderer/kustomization.yaml delete mode 100755 examples/kustomize-renderer/kustomize delete mode 100644 examples/kustomize-renderer/templates/environment.yaml delete mode 100644 examples/kustomize-renderer/values.yaml delete mode 100644 examples/medical-diagnosis-hub.yaml delete mode 100644 examples/secrets/values-secret.v1.yaml delete mode 100644 examples/secrets/values-secret.v2.yaml delete mode 100644 examples/values-example.yaml delete mode 100644 values-global.yaml diff --git a/examples/blank/Chart.yaml b/examples/blank/Chart.yaml deleted file mode 100644 index c552610d..00000000 --- a/examples/blank/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -description: An empty Helm chart -keywords: -- pattern -name: blank -version: 0.0.1 diff --git a/examples/blank/templates/manifest.yaml b/examples/blank/templates/manifest.yaml deleted file mode 100644 index 3f160b02..00000000 --- a/examples/blank/templates/manifest.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: example diff --git a/examples/blank/values.yaml b/examples/blank/values.yaml deleted file mode 100644 index 35e4a6f4..00000000 --- a/examples/blank/values.yaml +++ /dev/null @@ -1,2 +0,0 @@ -tree: - of: "values" diff --git a/examples/industrial-edge-factory.yaml b/examples/industrial-edge-factory.yaml deleted file mode 100644 index c60d0960..00000000 --- a/examples/industrial-edge-factory.yaml +++ /dev/null @@ -1,112 +0,0 @@ -clusterGroup: - name: factory - isHubCluster: false - - namespaces: - - manuela-stormshift-line-dashboard - - manuela-stormshift-machine-sensor - - manuela-stormshift-messaging - - manuela-factory-ml-workspace - - operatorgroupExcludes: - - manuela-factory-ml-workspace - - subscriptions: - - name: opendatahub-operator - channel: stable - source: community-operators - - - name: seldon-operator - namespace: manuela-stormshift-messaging - channel: stable - source: community-operators - - - name: amq-streams - namespace: manuela-stormshift-messaging - channel: stable - - - name: amq-broker-rhel8 - namespace: manuela-stormshift-messaging - channel: 7.x - - - name: red-hat-camel-k - namespace: manuela-stormshift-messaging - channel: stable - - projects: - - factory - - argoCD: - configManagementPlugins: - - name: helm-with-kustomize - image: quay.io/hybridcloudpatterns/utility-container:latest - pluginArgs: - - '--loglevel=debug' - pluginConfig: | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-{{ .Values.clusterGroup.name }}.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern={{ .Values.global.pattern }} - --set global.clusterDomain={{ .Values.global.clusterDomain }} - --set global.hubClusterDomain={{ .Values.global.hubClusterDomain }} - --set global.localClusterDomain={{ coalesce .Values.global.localClusterDomain .Values.global.hubClusterDomain }} - --set clusterGroup.name={{ .Values.clusterGroup.name }} - --post-renderer ./kustomize"] - - applications: - - name: stormshift - project: factory - path: charts/factory/manuela-stormshift - plugin: - name: helm-with-kustomize - - - name: odh - namespace: manuela-factory-ml-workspace - project: factory - path: charts/datacenter/opendatahub - -# -# To have apps in multiple flavors, use namespaces and use helm overrides as appropriate -# -# - name: pipelines -# namespace: production -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: stable -# overrides: -# - name: myparam -# value: myparam -# -# - name: pipelines -# namespace: staging -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: main -# -# Additional applications -# Be sure to include additional resources your apps will require -# +X machines -# +Y RAM -# +Z CPU -# - name: vendor-app -# namespace: default -# project: vendor -# path: path/to/myapp -# repoURL: https://github.com/vendor/applications.git -# targetRevision: main diff --git a/examples/industrial-edge-hub.yaml b/examples/industrial-edge-hub.yaml deleted file mode 100644 index e48c4013..00000000 --- a/examples/industrial-edge-hub.yaml +++ /dev/null @@ -1,241 +0,0 @@ -clusterGroup: - name: datacenter - isHubCluster: true - - namespaces: - - golang-external-secrets - - external-secrets - - open-cluster-management - - manuela-ml-workspace - - manuela-tst-all - - manuela-ci - - manuela-data-lake - - staging - - vault - - operatorgroupExcludes: - - manuela-ml-workspace - - subscriptions: - acm: - name: advanced-cluster-management - namespace: open-cluster-management - channel: release-2.6 - - amqbroker-prod: - name: amq-broker-rhel8 - namespace: manuela-tst-all - channel: 7.x - - amqstreams-prod-dev: - name: amq-streams - namespaces: - - manuela-data-lake - - manuela-tst-all - channel: stable - - camelk-prod-dev: - name: red-hat-camel-k - namespaces: - - manuela-data-lake - - manuela-tst-all - channel: stable - - seldon-prod-dev: - name: seldon-operator - namespaces: - - manuela-ml-workspace - - manuela-tst-all - channel: stable - source: community-operators - - pipelines: - name: openshift-pipelines-operator-rh - channel: latest - source: redhat-operators - - odh: - name: opendatahub-operator - channel: stable - source: community-operators - - projects: - - datacenter - - production-datalake - - golang-external-secrets - - vault - - argoCD: - configManagementPlugins: - - name: helm-with-kustomize - image: quay.io/hybridcloudpatterns/utility-container:latest - pluginArgs: - - '--loglevel=debug' - pluginConfig: | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-{{ .Values.clusterGroup.name }}.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern={{ .Values.global.pattern }} - --set global.clusterDomain={{ .Values.global.clusterDomain }} - --set global.hubClusterDomain={{ .Values.global.hubClusterDomain }} - --set global.localClusterDomain={{ coalesce .Values.global.localClusterDomain .Values.global.hubClusterDomain }} - --set clusterGroup.name={{ .Values.clusterGroup.name }} - --post-renderer ./kustomize"] - - applications: - acm: - name: acm - namespace: open-cluster-management - project: datacenter - path: common/acm - ignoreDifferences: - - group: internal.open-cluster-management.io - kind: ManagedClusterInfo - jsonPointers: - - /spec/loggingCA - - odh: - name: odh - namespace: manuela-ml-workspace - project: datacenter - path: charts/datacenter/opendatahub - - pipelines: - name: pipelines - namespace: manuela-ci - project: datacenter - path: charts/datacenter/pipelines - - production-data-lake: - name: production-data-lake - namespace: manuela-data-lake - project: production-datalake - path: charts/datacenter/manuela-data-lake - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status - - group: image.openshift.io - kind: ImageStream - jsonPointers: - - /spec/tags - - group: apps.openshift.io - kind: DeploymentConfig - jsonPointers: - - /spec/template/spec/containers/0/image - - test: - name: manuela-test - namespace: manuela-tst-all - project: datacenter - path: charts/datacenter/manuela-tst - plugin: - name: helm-with-kustomize - - vault: - name: vault - namespace: vault - project: datacenter - chart: vault - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - overrides: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: LoadBalancer - - name: server.route.enabled - value: "true" - - name: server.route.host - value: null - - name: server.route.tls.termination - value: edge - - name: server.image.repository - value: "registry.connect.redhat.com/hashicorp/vault" - - name: server.image.tag - value: "1.10.3-ubi" - - secrets-operator: - name: golang-external-secrets - namespace: golang-external-secrets - project: golang-external-secrets - path: common/golang-external-secrets - - secrets: - name: external-secrets - namespace: external-secrets - project: golang-external-secrets - path: charts/datacenter/external-secrets - -# To have apps in multiple flavors, use namespaces and use helm overrides as appropriate -# -# - name: pipelines -# namespace: production -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: stable -# overrides: -# - name: myparam -# value: myparam -# -# - name: pipelines -# namespace: staging -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: main -# -# Additional applications -# Be sure to include additional resources your apps will require -# +X machines -# +Y RAM -# +Z CPU -# - name: vendor-app -# namespace: default -# project: vendor -# path: path/to/myapp -# repoURL: https://github.com/vendor/applications.git -# targetRevision: main - - managedClusterGroups: - factory: - name: factory - # repoURL: https://github.com/dagger-refuse-cool/manuela-factory.git - # targetRevision: main - helmOverrides: - # Values must be strings! - - name: clusterGroup.isHubCluster - value: "false" - clusterSelector: - matchLabels: - clusterGroup: factory - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - diff --git a/examples/kustomize-renderer/Chart.yaml b/examples/kustomize-renderer/Chart.yaml deleted file mode 100644 index 88a786c9..00000000 --- a/examples/kustomize-renderer/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -description: A Helm chart to demonstrate how to use with kustomize -keywords: -- pattern -name: example -version: 0.0.1 diff --git a/examples/kustomize-renderer/environment.yaml b/examples/kustomize-renderer/environment.yaml deleted file mode 100644 index de4c48a9..00000000 --- a/examples/kustomize-renderer/environment.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: environment -data: - IMAGE_PROVIDER: {{ .Values.global.imageregistry.hostname }} - IMAGE_ACCOUNT: {{ .Values.global.imageregistry.account }} - GIT_EMAIL: {{ .Values.global.git.email }} - GIT_DEV_REPO_URL: https://{{ .Values.global.git.hostname }}/{{ .Values.global.git.account }}/manuela-dev.git - GIT_DEV_REPO_REVISION: {{ .Values.global.git.dev_revision }} - GIT_OPS_REPO_TEST_URL: {{ .Values.global.repoURL }} - GIT_OPS_REPO_TEST_REVISION: {{ .Values.global.targetRevision }} - GIT_OPS_REPO_PROD_URL: {{ .Values.global.repoURL }} - GIT_OPS_REPO_PROD_REVISION: {{ .Values.global.targetRevision }} - IOT_CONSUMER_IMAGE: iot-consumer - IOT_CONSUMER_YAML_PATH: images.(name==messaging).newTag - IOT_CONSUMER_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_CONSUMER_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/messaging/kustomization.yaml - IOT_CONSUMER_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/messaging/messaging-is.yaml - IOT_FRONTEND_IMAGE: iot-frontend - IOT_FRONTEND_YAML_PATH: images.(name==line-dashboard).newTag - IOT_FRONTEND_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_FRONTEND_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/line-dashboard/kustomization.yaml - IOT_FRONTEND_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/line-dashboard/line-dashboard-is.yaml - IOT_SWSENSOR_IMAGE: iot-software-sensor - IOT_SWSENSOR_YAML_PATH: images.(name==machine-sensor).newTag - IOT_SWSENSOR_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_SWSENSOR_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/machine-sensor/kustomization.yaml - IOT_SWSENSOR_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/machine-sensor/machine-sensor-is.yaml - IOT_ANOMALY_IMAGE: iot-anomaly-detection - IOT_ANOMALY_YAML_PATH: images.(name==anomaly-detection).newTag - IOT_ANOMALY_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_ANOMALY_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/anomaly-detection/kustomization.yaml - IOT_ANOMALY_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/anomaly-detection/anomaly-detection-is.yaml diff --git a/examples/kustomize-renderer/kustomization.yaml b/examples/kustomize-renderer/kustomization.yaml deleted file mode 100644 index 8d8bcd10..00000000 --- a/examples/kustomize-renderer/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -resources: - - environment.yaml - -patches: -- helm.patch.yaml diff --git a/examples/kustomize-renderer/kustomize b/examples/kustomize-renderer/kustomize deleted file mode 100755 index 3266d453..00000000 --- a/examples/kustomize-renderer/kustomize +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -x - -BASE=`dirname $0` -if [ $BASE = $PWD ]; then - BASE=./ -fi - -cat <&0 > "$BASE/helm.yaml" - -# Including at least one log to stderr allows us to see the full -x output -echo $HOME $PWD 1>&2 -ls -al 1>&2 - -kustomize build "$BASE" && rm "$BASE/helm.yaml" diff --git a/examples/kustomize-renderer/templates/environment.yaml b/examples/kustomize-renderer/templates/environment.yaml deleted file mode 100644 index de4c48a9..00000000 --- a/examples/kustomize-renderer/templates/environment.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: environment -data: - IMAGE_PROVIDER: {{ .Values.global.imageregistry.hostname }} - IMAGE_ACCOUNT: {{ .Values.global.imageregistry.account }} - GIT_EMAIL: {{ .Values.global.git.email }} - GIT_DEV_REPO_URL: https://{{ .Values.global.git.hostname }}/{{ .Values.global.git.account }}/manuela-dev.git - GIT_DEV_REPO_REVISION: {{ .Values.global.git.dev_revision }} - GIT_OPS_REPO_TEST_URL: {{ .Values.global.repoURL }} - GIT_OPS_REPO_TEST_REVISION: {{ .Values.global.targetRevision }} - GIT_OPS_REPO_PROD_URL: {{ .Values.global.repoURL }} - GIT_OPS_REPO_PROD_REVISION: {{ .Values.global.targetRevision }} - IOT_CONSUMER_IMAGE: iot-consumer - IOT_CONSUMER_YAML_PATH: images.(name==messaging).newTag - IOT_CONSUMER_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_CONSUMER_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/messaging/kustomization.yaml - IOT_CONSUMER_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/messaging/messaging-is.yaml - IOT_FRONTEND_IMAGE: iot-frontend - IOT_FRONTEND_YAML_PATH: images.(name==line-dashboard).newTag - IOT_FRONTEND_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_FRONTEND_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/line-dashboard/kustomization.yaml - IOT_FRONTEND_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/line-dashboard/line-dashboard-is.yaml - IOT_SWSENSOR_IMAGE: iot-software-sensor - IOT_SWSENSOR_YAML_PATH: images.(name==machine-sensor).newTag - IOT_SWSENSOR_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_SWSENSOR_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/machine-sensor/kustomization.yaml - IOT_SWSENSOR_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/machine-sensor/machine-sensor-is.yaml - IOT_ANOMALY_IMAGE: iot-anomaly-detection - IOT_ANOMALY_YAML_PATH: images.(name==anomaly-detection).newTag - IOT_ANOMALY_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_ANOMALY_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/anomaly-detection/kustomization.yaml - IOT_ANOMALY_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/anomaly-detection/anomaly-detection-is.yaml diff --git a/examples/kustomize-renderer/values.yaml b/examples/kustomize-renderer/values.yaml deleted file mode 100644 index cb80a03a..00000000 --- a/examples/kustomize-renderer/values.yaml +++ /dev/null @@ -1,12 +0,0 @@ -global: - git: - provider: github.com - account: PLAINTEXT - username: PLAINTEXT - email: SOMEWHERE@EXAMPLE.COM - dev_revision: main - - imageregistry: - provider: quay.io - account: PLAINTEXT - diff --git a/examples/medical-diagnosis-hub.yaml b/examples/medical-diagnosis-hub.yaml deleted file mode 100644 index 8bde30d0..00000000 --- a/examples/medical-diagnosis-hub.yaml +++ /dev/null @@ -1,228 +0,0 @@ -clusterGroup: - name: hub - isHubCluster: true - - namespaces: - - open-cluster-management - - openshift-serverless - - opendatahub - - openshift-storage - - xraylab-1 - - knative-serving - - staging - - vault - - golang-external-secrets - - subscriptions: - amq-streams: - name: amq-streams - namespace: xraylab-1 - channel: stable - - grafana: - name: grafana-operator - namespace: xraylab-1 - channel: v4 - source: community-operators - - odf: - name: odf-operator - namespace: openshift-storage - channel: stable-4.11 - - severless: - name: serverless-operator - channel: stable - - opendatahub: - name: opendatahub-operator - source: community-operators - - projects: - - hub - - medical-diagnosis - - applications: - vault: - name: vault - namespace: vault - project: hub - chart: vault - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - overrides: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: LoadBalancer - - name: server.route.enabled - value: "true" - - name: server.route.host - value: null - - name: server.route.tls.termination - value: edge - - name: server.image.repository - value: "registry.connect.redhat.com/hashicorp/vault" - - name: server.image.tag - value: "1.10.3-ubi" - - golang-external-secrets: - name: golang-external-secrets - namespace: golang-external-secrets - project: hub - path: common/golang-external-secrets - - opendatahub: - name: odh - namespace: opendatahub - project: medical-diagnosis - path: charts/all/opendatahub - - openshift-data-foundations: - name: odf - namespace: openshift-storage - project: medical-diagnosis - path: charts/all/openshift-data-foundations - - openshift-serverless: - name: serverless - namespace: xraylab-1 - project: medical-diagnosis - path: charts/all/openshift-serverless - - kafka: - name: kafka - namespace: xraylab-1 - project: medical-diagnosis - path: charts/all/kafka - - kafdrop: - name: kafdrop - namespace: xraylab-1 - project: medical-diagnosis - path: charts/all/kafdrop - - service-account: - name: xraylab-service-account - namespace: xraylab-1 - project: medical-diagnosis - path: charts/all/medical-diagnosis/service-account - - xraylab-init: - name: xraylab-init - namespace: xraylab-1 - project: medical-diagnosis - path: charts/all/medical-diagnosis/xray-init - - xraylab-database: - name: xraylab-database - namespace: xraylab-1 - project: medical-diagnosis - path: charts/all/medical-diagnosis/database - - xraylab-grafana-dashboards: - name: xraylab-grafana-dashboards - namespace: xraylab-1 - project: medical-diagnosis - path: charts/all/medical-diagnosis/grafana - - xraylab-image-server: - name: xraylab-image-server - namespace: xraylab-1 - project: medical-diagnosis - path: charts/all/medical-diagnosis/image-server - ignoreDifferences: - - group: apps.openshift.io - kind: DeploymentConfig - jqPathExpressions: - - '.spec.template.spec.containers[].image' - - xraylab-image-generator: - name: xraylab-image-generator - namespace: xraylab-1 - project: medical-diagnosis - path: charts/all/medical-diagnosis/image-generator - ignoreDifferences: - - group: apps.openshift.io - kind: DeploymentConfig - jqPathExpressions: - - '.spec.template.spec.containers[].image' - - imperative: - # NOTE: We *must* use lists and not hashes. As hashes lose ordering once parsed by helm - # The default schedule is every 10 minutes: imperative.schedule - # Total timeout of all jobs is 1h: imperative.activeDeadlineSeconds - # imagePullPolicy is set to always: imperative.imagePullPolicy - # For additional overrides that apply to the jobs, please refer to - # https://hybrid-cloud-patterns.io/imperative-actions/#additional-job-customizations - jobs: - - name: regional-ca - # ansible playbook to be run - playbook: ansible/playbooks/on-hub-get-regional-ca.yml - # per playbook timeout in seconds - timeout: 234 - # verbosity: "-v" - - managedClusterGroups: - region-one: - name: region-one - helmOverrides: - - name: clusterGroup.isHubCluster - value: false - clusterSelector: - matchLabels: - clusterGroup: region-one - -# To have apps in multiple flavors, use namespaces and use helm overrides as appropriate -# -# pipelines: -# name: pipelines -# namespace: production -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: stable -# overrides: -# - name: myparam -# value: myparam -# -# pipelines_staging: -# - name: pipelines -# namespace: staging -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: main -# -# Additional applications -# Be sure to include additional resources your apps will require -# +X machines -# +Y RAM -# +Z CPU -# vendor-app: -# name: vendor-app -# namespace: default -# project: vendor -# path: path/to/myapp -# repoURL: https://github.com/vendor/applications.git -# targetRevision: main - -# managedSites: -# factory: -# name: factory -# # repoURL: https://github.com/dagger-refuse-cool/manuela-factory.git -# targetRevision: main -# path: applications/factory -# helmOverrides: -# - name: site.isHubCluster -# value: false -# clusterSelector: -# matchExpressions: -# - key: vendor -# operator: In -# values: -# - OpenShift diff --git a/examples/secrets/values-secret.v1.yaml b/examples/secrets/values-secret.v1.yaml deleted file mode 100644 index c04e8262..00000000 --- a/examples/secrets/values-secret.v1.yaml +++ /dev/null @@ -1,33 +0,0 @@ ---- -# By default when a top-level 'version: "1.0"' is missing it is assumed to be '1.0' -# NEVER COMMIT THESE VALUES TO GIT - -secrets: - # These secrets will be pushed in the vault at secret/hub/test The vault will - # have secret/hub/test with secret1 and secret2 as keys with their associated - # values (secrets) - test: - secret1: foo - secret2: bar - - # This ends up as the s3Secret attribute to the path secret/hub/aws - aws: - s3Secret: test-secret - -# This will create the vault key secret/hub/testfoo which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files: - testfoo: ~/ca.crt -# These secrets will be pushed in the vault at secret/region1/test The vault will -# have secret/region1/test with secret1 and secret2 as keys with their associated -# values (secrets) -secrets.region1: - test: - secret1: foo1 - secret2: bar1 -# This will create the vault key secret/region2/testbar which will have two -# properties 'b64content' and 'content' which will be the base64-encoded -# content and the normal content respectively -files.region2: - testbar: ~/ca.crt diff --git a/examples/secrets/values-secret.v2.yaml b/examples/secrets/values-secret.v2.yaml deleted file mode 100644 index eab81a38..00000000 --- a/examples/secrets/values-secret.v2.yaml +++ /dev/null @@ -1,114 +0,0 @@ -# NEVER COMMIT THESE VALUES TO GIT (unless your file only uses generated -# passwords or only points to files) - -# NOTE: If you edit this file, make sure to also reflect the changes in the corresponding -# schema file - -# Needed to specify the new format (missing version means old version: 1.0 by default) -version: "2.0" - -backingStore: vault # 'vault' is the default when omitted - -# These are the vault policies to be created in the vault -# these are used when we let the vault generate the passwords -# by setting the 'onMissingValue' attribute to 'generate' -# See https://developer.hashicorp.com/vault/docs/concepts/password-policies -vaultPolicies: - basicPolicy: | - length=10 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - - advancedPolicy: | - length=20 - rule "charset" { charset = "abcdefghijklmnopqrstuvwxyz" min-chars = 1 } - rule "charset" { charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" min-chars = 1 } - rule "charset" { charset = "0123456789" min-chars = 1 } - rule "charset" { charset = "!@#$%^&*" min-chars = 1 } - -# This is the mandatory top-level secrets entry -secrets: - - name: aws - fields: - - name: aws_access_key_id - ini_file: ~/.aws/credentials - ini_key: aws_access_key_id - # You can actually omit this as it is the default - # it is here, because I believe the json schema validator has a bug - # (it ignores the default value of onMissingValue in the aallOf if checks) - onMissingValue: error - # ini_section: default - - name: aws_secret_access_key - onMissingValue: error - ini_file: ~/.aws/credentials - ini_key: aws_secret_access_key - # ini_section: default - - - name: config-demo - vaultMount: secret - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: secret - onMissingValue: generate - override: true - vaultPolicy: basicPolicy - - name: secretprompt - value: null - onMissingValue: prompt - prompt: "Please specify the password for application ABC" - - name: secretprompt2 - value: defaultvalue - onMissingValue: prompt - prompt: "Please specify the API key for XYZ" - - name: secretfile - path: /tmp/ca.crt - onMissingValue: prompt - prompt: "Insert path to Certificate Authority" - - name: ca_crt - path: /tmp/ca.crt - onMissingValue: error - - name: ca_crt_b64 - path: /tmp/ca.crt - base64: true # defaults to false - onMissingValue: prompt - - - name: config-demo2 - vaultPrefixes: - - region-one - - snowflake.blueprints.rhecoeng.com - fields: - - name: ca_crt2 - path: null - onMissingValue: prompt - - name: ca_crt - path: /tmp/ca.crt - onMissingValue: error - - # This will be uploaded to the 'hub' vaultPrefix as it is the default when - # omitted - - name: config-demo3 - fields: - - name: ca_crt2 - path: null - onMissingValue: prompt - - name: ca_crt - path: /tmp/ca.crt - onMissingValue: error - # - # The cluster_xxxx pattern is used for creating externalSecrets that - # will be used by ArgoCD to push manifests to other clusters. - # - # oc extract -n openshift-config cm/kube-root-ca.crt --to=/home/user/ --keys=ca.crt --confirm - - name: cluster_foocluster - fields: - - name: bearerToken - value: - onMissingValue: error - - name: caCert - # See command above - path: /home/user/ca.crt - onMissingValue: error - base64: true diff --git a/examples/values-example.yaml b/examples/values-example.yaml deleted file mode 100644 index 312155b9..00000000 --- a/examples/values-example.yaml +++ /dev/null @@ -1,207 +0,0 @@ -global: - options: - useCSV: False - syncPolicy: Automatic - installPlanApproval: Automatic - multiClusterTarget: all - -#enabled: all - -clusterGroup: - name: example - #insecureUnsealVaultInsideCluster: false - isHubCluster: true - sharedValueFiles: - - /values/{{ .Values.global.clusterPlatform }}.yaml - - /values/{{ .Values.global.clusterVersion }}.yaml - - scheduler: - mastersSchedulable: true - - # You can define namespaces using hashes and not as a list like so: - # namespaces: - # open-cluster-management: - # labels: - # openshift.io/node-selector: "" - # kubernetes.io/os: linux - # annotations: - # openshift.io/cluster-monitoring: "true" - # owner: "namespace owner" - # application-ci: - # You cannot mix list and hashes to define namespaces - namespaces: - - open-cluster-management: - labels: - openshift.io/node-selector: "" - kubernetes.io/os: linux - annotations: - openshift.io/cluster-monitoring: "true" - owner: "namespace owner" - - application-ci: - operatorGroup: true - targetNamespaces: - - application-ci - - other-namespace - - exclude-targetns: - operatorGroup: true - targetNamespaces: - - include-ci - - exclude-og - - totally-exclude-og: - operatorGroup: false - - include-default-og: - operatorGroup: true - - nodes: - - m-m00.cluster.example.tld: - labels: - cluster.ocs.openshift.io/openshift-storage: "" - - m-m01.cluster.example.tld: - labels: - cluster.ocs.openshift.io/openshift-storage: "" - - m-m02.cluster.example.tld: - labels: - cluster.ocs.openshift.io/openshift-storage: "" - - operatorgroupExcludes: - - exclude-og - - subscriptions: - acm: - name: advanced-cluster-management - namespace: open-cluster-management - channel: release-2.4 - csv: advanced-cluster-management.v2.4.1 - - odh: - name: opendatahub-operator - source: community-operators - csv: opendatahub-operator.v1.1.0 - disabled: true - - pipelines: - name: openshift-pipelines-operator-rh - csv: redhat-openshift-pipelines.v1.5.2 - - # - # You can define projects using hashes like so: - # projects: - # hub: - # datacenter: - # You cannot mix list and hashes to define projects. - projects: - - datacenter - - applications: - acm: - name: acm - namespace: open-cluster-management - project: datacenter - path: common/acm - ignoreDifferences: - - group: internal.open-cluster-management.io - kind: ManagedClusterInfo - jsonPointers: - - /spec/loggingCA - pipe: - name: pipelines - namespace: application-ci - project: datacenter - path: charts/datacenter/pipelines - extraValueFiles: - - /values/{{ .Values.global.clusterVersion }}/{{ .Values.global.clusterPlatform }}.yaml - - imperative: - namespace: imperative - # NOTE: We *must* use lists and not hashes. As hashes lose ordering once parsed by helm - # The default schedule is every 10 minutes: imperative.schedule - # Total timeout of all jobs is 1h: imperative.activeDeadlineSeconds - # imagePullPolicy is set to always: imperative.imagePullPolicy - # For additional overrides that apply to the jobs, please refer to - # https://hybrid-cloud-patterns.io/imperative-actions/#additional-job-customizations - jobs: - - name: regional-ca - # ansible playbook to be run - playbook: ansible/playbooks/on-hub-get-regional-ca.yml - # per playbook timeout in seconds - timeout: 234 - # verbosity: "-v" - - managedClusterGroups: - - name: acm-edge - # Optional - Point to a different repo - # repoURL: https://github.com/hybrid-cloud-patterns/mySite.git - # Must contain values-{clustergroupname}.yaml at the top level - targetRevision: main - helmOverrides: - # Values must be strings! - - name: clusterGroup.isHubCluster - value: "false" - acmlabels: - - name: clusterGroup - value: acm-region - - name: acm-provision-edge - targetRevision: main - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" - clusterPools: - exampleAWSPool: - size: 3 - name: aws-ap - openshiftVersion: 4.10.18 - baseDomain: blueprints.rhecoeng.com - controlPlane: - count: 1 - platform: - aws: - type: m5.xlarge - workers: - count: 0 - platform: - aws: - region: ap-southeast-2 - exampleAzurePool: - name: azure-us - openshiftVersion: 4.10.18 - baseDomain: blueprints.rhecoeng.com - platform: - azure: - baseDomainResourceGroupName: dojo-dns-zones - region: eastus - clusters: - - Two - - three - clusterDeployments: - myFirstCluster: - name: aws-cd-one-w-pool - openshiftVersion: 4.10.18 - baseDomain: blueprints.rhecoeng.com - platform: - aws: - region: ap-southeast-1 - acmlabels: - - name: clusterGroup - value: region - - name: acm-provision-on-deploy - clusterDeployments: - mySecondCluster: - name: aws-cd-two-wo-pool - openshiftVersion: 4.10.18 - baseDomain: blueprints.rhecoeng.com - platform: - aws: - region: ap-southeast-3 - - name: argo-edge - hostedArgoSites: - - name: perth - domain: perth1.beekhof.net - # The default is secret/data/hub/cluster_ - #secretsPath: secret/data/hub/cluster_perth - - name: sydney - domain: syd.beekhof.net - # The default is secret/data/hub/cluster_ - #secretsPath: secret/data/hub/cluster_sydney - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" diff --git a/values-global.yaml b/values-global.yaml deleted file mode 100644 index 684f89f2..00000000 --- a/values-global.yaml +++ /dev/null @@ -1,20 +0,0 @@ -global: - options: - useCSV: True - syncPolicy: Manual - installPlanApproval: Automatic - applicationRetryLimit: 20 - - git: - hostname: github.com - # Account is the user or organization under which the pattern repos lives - account: hybrid-cloud-patterns - email: someone@somewhere.com - dev_revision: main - - secretStore: - backend: vault - -main: - clusterGroupName: example - From c77f74dc8cfd0fef5b9a3322e06b9b684c9e6aca Mon Sep 17 00:00:00 2001 From: Andrew Beekhof Date: Thu, 26 Sep 2024 09:36:48 +1000 Subject: [PATCH 187/222] We don't have charts to test anymore --- .github/workflows/linter.yml | 65 ------------------------------------ 1 file changed, 65 deletions(-) delete mode 100644 .github/workflows/linter.yml diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml deleted file mode 100644 index f82194ee..00000000 --- a/.github/workflows/linter.yml +++ /dev/null @@ -1,65 +0,0 @@ ---- -name: Unit test common - -# -# Documentation: -# https://help.github.com/en/articles/workflow-syntax-for-github-actions -# - -############################# -# Start the job on all push # -############################# -on: [push, pull_request] - -############### -# Set the Job # -############### -jobs: - build: - # Name the Job - name: Unit common/ Code Base - # Set the agent to run on - runs-on: ubuntu-latest - - ################## - # Load all steps # - ################## - steps: - ########################## - # Checkout the code base # - ########################## - - name: Checkout Code - uses: actions/checkout@v4 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - name: Setup helm - uses: azure/setup-helm@v4 - with: - version: 'v3.14.0' - - - ################################ - # Run Linter against code base # - ################################ - # - name: Lint Code Base - # uses: github/super-linter@v4 - # env: - # VALIDATE_ALL_CODEBASE: false - # DEFAULT_BRANCH: main - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Run make test - run: | - make test - - - name: Run make helmlint - run: | - make helmlint - - # For now disable this until we have a nice and simple process to update the schemas in our repo - # - name: Run make helm kubeconform - # run: | - # curl -L -O https://github.com/yannh/kubeconform/releases/download/v0.4.13/kubeconform-linux-amd64.tar.gz - # tar xf kubeconform-linux-amd64.tar.gz - # sudo mv -v kubeconform /usr/local/bin - # make kubeconform From bb4419523f65cd5681ce8e9732cb13b64e7af651 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 26 Sep 2024 11:17:20 +0200 Subject: [PATCH 188/222] Drop lint.sh and its target in Makefile --- Makefile | 4 ---- scripts/lint.sh | 18 ------------------ 2 files changed, 22 deletions(-) delete mode 100755 scripts/lint.sh diff --git a/Makefile b/Makefile index ce4a4a91..a1318797 100644 --- a/Makefile +++ b/Makefile @@ -226,10 +226,6 @@ EXECUTABLES=git helm oc ansible test: ## run helm tests @for t in $(CHARTS); do common/scripts/test.sh $$t all "$(TEST_OPTS)"; if [ $$? != 0 ]; then exit 1; fi; done -.PHONY: helmlint -helmlint: ## run helm lint - @for t in $(CHARTS); do common/scripts/lint.sh $$t $(TEST_OPTS); if [ $$? != 0 ]; then exit 1; fi; done - API_URL ?= https://raw.githubusercontent.com/hybrid-cloud-patterns/ocp-schemas/main/openshift/4.10/ KUBECONFORM_SKIP ?= -skip 'CustomResourceDefinition,ClusterIssuer,CertManager,Certificate,ArgoCD' diff --git a/scripts/lint.sh b/scripts/lint.sh deleted file mode 100755 index 3a3d8e6f..00000000 --- a/scripts/lint.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# helm template (even with --dry-run) can interact with the cluster -# This won't protect us if a user has ~/.kube -# Also call helm template with a non existing --kubeconfig while we're at it -unset KUBECONFIG -target=$1 -shift -name=$(echo $target | sed -e s@/@-@g -e s@charts-@@) - -# Test the charts as the pattern would drive them -INPUTS=$(ls -1 common/examples/*.yaml | grep -v secret) -for input in $INPUTS; do - helm lint $* -f $input $target - if [ $? != 0 ]; then exit 1; fi -done - -exit 0 From 60d921f0b14c47ba0ff6afe399b2fd92db520012 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 26 Sep 2024 11:18:21 +0200 Subject: [PATCH 189/222] Drop test.sh and its target in Makefile and also kubeconform --- Makefile | 29 ----------- scripts/test.sh | 129 ------------------------------------------------ 2 files changed, 158 deletions(-) delete mode 100755 scripts/test.sh diff --git a/Makefile b/Makefile index a1318797..24fba8a0 100644 --- a/Makefile +++ b/Makefile @@ -205,35 +205,6 @@ argo-healthcheck: ## Checks if all argo applications are synced ##@ Test and Linters Tasks -CHARTS=$(shell find . -type f -iname 'Chart.yaml' -exec dirname "{}" \; | grep -v examples | sed -e 's/.\///') -# Section related to tests and linting -TEST_OPTS= -f values-global.yaml \ - --set global.repoURL="https://github.com/pattern-clone/mypattern" \ - --set main.git.repoURL="https://github.com/pattern-clone/mypattern" \ - --set main.git.revision=main --set global.pattern="mypattern" \ - --set global.namespace="pattern-namespace" \ - --set global.hubClusterDomain=apps.hub.example.com \ - --set global.localClusterDomain=apps.region.example.com \ - --set global.clusterDomain=region.example.com \ - --set global.clusterVersion="4.12" \ - --set global.clusterPlatform=aws \ - --set "clusterGroup.imperative.jobs[0].name"="test" \ - --set "clusterGroup.imperative.jobs[0].playbook"="rhvp.cluster_utils.test" -PATTERN_OPTS=-f common/examples/values-example.yaml -EXECUTABLES=git helm oc ansible - -.PHONY: test -test: ## run helm tests - @for t in $(CHARTS); do common/scripts/test.sh $$t all "$(TEST_OPTS)"; if [ $$? != 0 ]; then exit 1; fi; done - -API_URL ?= https://raw.githubusercontent.com/hybrid-cloud-patterns/ocp-schemas/main/openshift/4.10/ -KUBECONFORM_SKIP ?= -skip 'CustomResourceDefinition,ClusterIssuer,CertManager,Certificate,ArgoCD' - -# We need to skip 'CustomResourceDefinition' as openapi2jsonschema seems to be unable to generate them ATM -.PHONY: kubeconform -kubeconform: ## run helm kubeconform - @for t in $(CHARTS); do helm template $(TEST_OPTS) $(PATTERN_OPTS) $$t | kubeconform -strict $(KUBECONFORM_SKIP) -verbose -schema-location $(API_URL); if [ $$? != 0 ]; then exit 1; fi; done - .PHONY: super-linter super-linter: ## Runs super linter locally rm -rf .mypy_cache diff --git a/scripts/test.sh b/scripts/test.sh deleted file mode 100755 index a2aae9f4..00000000 --- a/scripts/test.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash - -# helm template (even with --dry-run) can interact with the cluster -# This won't protect us if a user has ~/.kube -# Also call helm template with a non existing --kubeconfig while we're at it -unset KUBECONFIG -target=$1 -name=$(echo $1 | sed -e s@/@-@g -e s@charts-@@) - -function doTest() { - TEST_VARIANT=$1 - CHART_OPTS="$2" - TESTDIR=tests - TEST=${name}-${TEST_VARIANT} - FILENAME=${TEST}.expected.yaml - OUTPUT=${TESTDIR}/.${FILENAME} - REFERENCE=${TESTDIR}/${FILENAME} - - echo -e "\nTesting $name chart (${TEST_VARIANT}) with opts [$CHART_OPTS]" >&2 - helm template --kubeconfig /tmp/doesnotexistever $target --name-template $name ${CHART_OPTS} > ${OUTPUT} - rc=$? - if [ $rc -ne 0 ]; then - echo "FAIL on helm template $target --name-template $name ${CHART_OPTS}" >&2 - exit 1 - fi - if [ ! -e ${REFERENCE} ]; then - cp ${OUTPUT} ${REFERENCE} - git add ${REFERENCE} - echo -e "\n\n#### Created test output\007\n\n\007" >&2 - fi - diff -u ${REFERENCE} ${OUTPUT} - rc=$? - if [ $rc = 0 ]; then - rm -f ${OUTPUT} - echo "PASS" >&2 - elif [ -z $GITHUB_ACTIONS ]; then - read -p "Are these changes expected? [y/N] " EXPECTED - case $EXPECTED in - y*|Y*) - echo "Updating ${REFERENCE}" - cp ${OUTPUT} ${REFERENCE} - rm -f ${OUTPUT} - rc=0 - ;; - *) ;; - esac - fi - if [ $rc != 0 ]; then - echo "FAIL" >&2 - exit $rc - fi -} - -function doTestCompare() { - TEST_VARIANT="differences" - TESTDIR=tests - TEST=${name} - FILENAME=${TEST}.expected.yaml - OUTPUT=${TESTDIR}/.${FILENAME} - REFERENCE=${TESTDIR}/${FILENAME} - - echo -e "\nTesting $name chart (${TEST_VARIANT})" >&2 - # Another method of finding variables missing from values.yaml, eg. - # - name: -datacenter - # + name: pattern-name-datacenter - - TEST=${name} - FILENAME=${TEST}.expected.diff - OUTPUT=${TESTDIR}/.${FILENAME} - REFERENCE=${TESTDIR}/${FILENAME} - - # Drop the date from the diff output, it will not be stable - diff -u ${TESTDIR}/${name}-naked.expected.yaml ${TESTDIR}/${name}-normal.expected.yaml | sed 's/\.yaml.*20[0-9][0-9].*/.yaml/g' > ${OUTPUT} - - if [ ! -e ${REFERENCE} -a -z $GITHUB_ACTIONS ]; then - cp ${OUTPUT} ${REFERENCE} - git add ${REFERENCE} - echo -e "\n\n#### Created test output\007\n\n\007" >&2 - fi - - diff -u ${REFERENCE} ${OUTPUT} - rc=$? - - if [ $rc = 0 ]; then - rm -f ${OUTPUT} - echo "PASS" >&2 - elif [ -z $GITHUB_ACTIONS ]; then - read -p "Are these changes expected? [y/N] " EXPECTED - case $EXPECTED in - y*|Y*) - echo "Updating ${REFERENCE}" - cp ${OUTPUT} ${REFERENCE} - rm -f ${OUTPUT} - rc=0 - ;; - *) ;; - esac - fi - if [ $rc != 0 ]; then - echo "FAIL" >&2 - exit $rc - fi -} - -if [ $2 = "all" ]; then - echo -e "\n#####################" >&2 - echo "### ${name}" >&2 - echo "#####################" >&2 - - # Test that all values used by the chart are in values.yaml with the same defaults as the pattern - doTest naked - - # Test the charts as the pattern would drive them - INPUTS=$(ls -1 common/examples/*.yaml | grep -v secret) - for input in $INPUTS; do - variant=normal - if [ "$input" != "common/examples/values-example.yaml" ]; then - variant=$(echo $input | sed -e 's@.*/@@' -e 's@\.yaml@@') - fi - doTest $variant "$3 -f $input" - done - - # Ensure the differences between the two results are also stable - #doTestCompare -else - doTest $2 "$3" -fi - -exit 0 From ac54604f4c44a0a688415bfc7076c3a806bbd93a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sun, 29 Sep 2024 16:04:42 +0200 Subject: [PATCH 190/222] Read PATTERN_INSTALL_CHART from the env as well if it exists --- scripts/pattern-util.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index cb7fc873..675cc117 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -80,6 +80,7 @@ podman run -it --rm --pull=newer \ -e TOKEN_NAMESPACE \ -e VALUES_SECRET \ -e KUBECONFIG \ + -e PATTERN_INSTALL_CHART \ -e K8S_AUTH_HOST \ -e K8S_AUTH_VERIFY_SSL \ -e K8S_AUTH_SSL_CA_CERT \ From 0d1cda8eb362e82436d0cd276af84d740dbd52d1 Mon Sep 17 00:00:00 2001 From: Akos Eros Date: Mon, 30 Sep 2024 15:49:14 +0200 Subject: [PATCH 191/222] Update secret backend change script The script is used in make secrets-backend-*. Update needed for slimed common. --- scripts/manage-secret-app.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/manage-secret-app.sh b/scripts/manage-secret-app.sh index 1ea0d0bb..18a986e5 100755 --- a/scripts/manage-secret-app.sh +++ b/scripts/manage-secret-app.sh @@ -11,13 +11,17 @@ case "$APP" in APP_NAME="vault" NAMESPACE="vault" PROJECT="$MAIN_CLUSTERGROUP_PROJECT" - CHART_LOCATION="common/hashicorp-vault" + CHART_NAME="hashicorp-vault" + CHART_VERSION=0.1.* + ;; "golang-external-secrets") APP_NAME="golang-external-secrets" NAMESPACE="golang-external-secrets" PROJECT="$MAIN_CLUSTERGROUP_PROJECT" - CHART_LOCATION="common/golang-external-secrets" + CHART_NAME="golang-external-secrets" + CHART_VERSION=0.1.* + ;; *) echo "Error - cannot manage $APP can only manage vault and golang-external-secrets" @@ -32,13 +36,13 @@ case "$STATE" in RES=$(yq ".clusterGroup.applications[] | select(.path == \"$CHART_LOCATION\")" "$MAIN_CLUSTERGROUP_FILE" 2>/dev/null) if [ -z "$RES" ]; then echo "Application with chart location $CHART_LOCATION not found, adding" - yq -i ".clusterGroup.applications.$APP_NAME = { \"name\": \"$APP_NAME\", \"namespace\": \"$NAMESPACE\", \"project\": \"$PROJECT\", \"path\": \"$CHART_LOCATION\" }" "$MAIN_CLUSTERGROUP_FILE" + yq -i ".clusterGroup.applications.$APP_NAME = { \"name\": \"$APP_NAME\", \"namespace\": \"$NAMESPACE\", \"project\": \"$PROJECT\", \"chart\": \"$CHART_NAME\", \"chartVersion\": \"$CHART_VERSION\"}" "$MAIN_CLUSTERGROUP_FILE" fi ;; "absent") common/scripts/manage-secret-namespace.sh "$NAMESPACE" "$STATE" echo "Removing application wth chart location $CHART_LOCATION" - yq -i "del(.clusterGroup.applications[] | select(.path == \"$CHART_LOCATION\"))" "$MAIN_CLUSTERGROUP_FILE" + yq -i "del(.clusterGroup.applications[] | select(.chart == \"$CHART_NAME\"))" "$MAIN_CLUSTERGROUP_FILE" ;; *) echo "$STATE not supported" From b8640e051fe9df47b32e9e080f84fe18ce9711fe Mon Sep 17 00:00:00 2001 From: Akos Eros Date: Mon, 30 Sep 2024 15:53:01 +0200 Subject: [PATCH 192/222] Update preview script Now the preview will work with remote charts, and local charts as well. Default helm registry will be oci://quay.io/repository/hybridcloudpatterns/. --- scripts/preview.sh | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/scripts/preview.sh b/scripts/preview.sh index b9839c51..6da45785 100755 --- a/scripts/preview.sh +++ b/scripts/preview.sh @@ -2,8 +2,7 @@ # DISCLAIMER # -# - Parsing of applications needs to be more clever. Currently the code assumes that all -# targets will be local charts. This is not true, for example, in industrial-edge. +# - Parsing of applications needs to be more clever. # - There is currently not a mechanism to actually preview against multiple clusters # (i.e. a hub and a remote). All previews will be done against the current. # - Make output can be included in the YAML. @@ -22,11 +21,22 @@ if [ "${APPNAME}" != "clustergroup" ]; then # path: charts/all/foo # So we retrieve the actual index ("foobar") given the name attribute of the application APP=$(yq ".clusterGroup.applications | with_entries(select(.value.name == \"$APPNAME\")) | keys | .[0]" values-$SITE.yaml) - chart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) + isLocalHelmChart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) + if [ $isLocalHelmChart != "null" ]; then + chart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) + else + helmrepo=$(yq ".clusterGroup.applications.$APP.repoURL" values-$SITE.yaml) + helmrepo="${helmrepo:+oci://quay.io/hybridcloudpatterns}" + chartversion=$(yq ".clusterGroup.applications.$APP.chartVersion" values-$SITE.yaml) + chartname=$(yq ".clusterGroup.applications.$APP.chart" values-$SITE.yaml) + chart="${helmrepo}/${chartname} --version ${chartversion}" + fi namespace=$(yq ".clusterGroup.applications.$APP.namespace" values-$SITE.yaml) else APP=$APPNAME - chart="common/clustergroup" + clusterGroupChartVersion=$(yq ".main.multiSourceConfig.clusterGroupChartVersion" values-global.yaml) + helmrepo="oci://quay.io/hybridcloudpatterns" + chart="${helmrepo}/clustergroup --version ${clusterGroupChartVersion}" namespace="openshift-operators" fi pattern=$(yq ".global.pattern" values-global.yaml) From e9f638a293b4f2ae2cc73846130b2e6502cf0f1c Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 7 Oct 2024 09:20:17 +0200 Subject: [PATCH 193/222] Introduce PATTERN_DISCONNECTED_HOME When doing disconnected installations this allows for setting a single variable pointing to the internal disconnected registry. --- scripts/pattern-util.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 675cc117..1fcaee76 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -11,6 +11,16 @@ function version { if [ -z "$PATTERN_UTILITY_CONTAINER" ]; then PATTERN_UTILITY_CONTAINER="quay.io/hybridcloudpatterns/utility-container" fi +# If PATTERN_DISCONNECTED_HOME is set it will be used to populate both PATTERN_UTILITY_CONTAINER +# and PATTERN_INSTALL_CHART automatically +if [ -n "${PATTERN_DISCONNECTED_HOME}" ]; then + PATTERN_UTILITY_CONTAINER="${PATTERN_DISCONNECTED_HOME}/utility-container" + PATTERN_INSTALL_CHART="oci://${PATTERN_DISCONNECTED_HOME}/pattern-install" + echo "PATTERN_DISCONNECTED_HOME is set to ${PATTERN_DISCONNECTED_HOME}" + echo "Setting the following variables:" + echo " PATTERN_UTILITY_CONTAINER: ${PATTERN_UTILITY_CONTAINER}" + echo " PATTERN_INSTALL_CHART: ${PATTERN_INSTALL_CHART}" +fi readonly commands=(podman) for cmd in ${commands[@]}; do is_available "$cmd"; done @@ -81,6 +91,7 @@ podman run -it --rm --pull=newer \ -e VALUES_SECRET \ -e KUBECONFIG \ -e PATTERN_INSTALL_CHART \ + -e PATTERN_DISCONNECTED_HOME \ -e K8S_AUTH_HOST \ -e K8S_AUTH_VERIFY_SSL \ -e K8S_AUTH_SSL_CA_CERT \ From 7b6517090145e93b56f5ea429573aaa5b7e93ea3 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Martinez Date: Mon, 7 Oct 2024 13:22:56 +0200 Subject: [PATCH 194/222] Update Makefile to reflect a warning if no storageclass is present --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e0e040a9..e802d2dd 100644 --- a/Makefile +++ b/Makefile @@ -143,7 +143,7 @@ validate-cluster: ## Do some cluster validations before installing @oc cluster-info >/dev/null && echo "OK" || (echo "Error"; exit 1) @echo -n " storageclass: " @if [ `oc get storageclass -o go-template='{{printf "%d\n" (len .items)}}'` -eq 0 ]; then\ - echo "None Found"; exit 1;\ + echo "WARNING: No storageclass found";\ else\ echo "OK";\ fi From c8c0072c79e758066e5c92887ab0cc6d783bafc1 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 9 Oct 2024 21:50:07 +0200 Subject: [PATCH 195/222] Fix iib loading playbook name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After slimming common down the playbook needs renaming because collections have slightly different naming constraints. Previous error: ❯ ./pattern.sh make load-iib make -f common/Makefile load-iib make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' ERROR! the playbook: rhvp.cluster_utils.iib-ci could not be found make[1]: *** [common/Makefile:117: load-iib] Error 1 make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make: *** [Makefile:12: load-iib] Error 2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e0e040a9..db3c89d2 100644 --- a/Makefile +++ b/Makefile @@ -115,7 +115,7 @@ secrets-backend-none: ## Edits values files to remove secrets manager + ESO .PHONY: load-iib load-iib: ## CI target to install Index Image Bundles @set -e; if [ x$(INDEX_IMAGES) != x ]; then \ - ansible-playbook rhvp.cluster_utils.iib-ci; \ + ansible-playbook rhvp.cluster_utils.iib_ci; \ else \ echo "No INDEX_IMAGES defined. Bailing out"; \ exit 1; \ From e9f00b11de1539f54bad4ecd508adb7db7c45c89 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 14 Oct 2024 11:39:46 +0200 Subject: [PATCH 196/222] Improve validate-origin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we set the main.git.upstreamRepoURL then we need to check that one for the presence of the branch and not whatever is configured as the origin remote. Tested as follows: - Working upstreamRepoURL: ❯ yq -r '.main.git.repoUpstreamURL // (.main.git.repoUpstreamURL = "")' values-global.yaml https://github.com/mbaldessari/industrial-edge ❯ make validate-origin make -f common/Makefile validate-origin make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/industrial-edge' Checking repository: Upstream URL set to: https://github.com/mbaldessari/industrial-edge https://github.com/mbaldessari/industrial-edge - branch 'for-max-s3-kafka-fix': OK make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/industrial-edge' - upstreamRepoURL without the branch: ❯ yq -r '.main.git.repoUpstreamURL // (.main.git.repoUpstreamURL = "")' values-global.yaml https://github.com/mamurak/industrial-edge ❯ make validate-origin make -f common/Makefile validate-origin make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/industrial-edge' Checking repository: Upstream URL set to: https://github.com/mamurak/industrial-edge https://github.com/mamurak/industrial-edge - branch 'for-max-s3-kafka-fix': NOT FOUND make[1]: *** [common/Makefile:138: validate-origin] Error 1 make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/industrial-edge' make: *** [Makefile:24: validate-origin] Error 2 - No repoUpstreamURL set: ❯ yq -r '.main.git.repoUpstreamURL // (.main.git.repoUpstreamURL = "")' values-global.yaml ❯ ❯ make validate-origin make -f common/Makefile validate-origin make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/industrial-edge' Checking repository: https://github.com/mbaldessari/industrial-edge.git - branch 'for-max-s3-kafka-fix': OK make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/industrial-edge' --- Makefile | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index a5c102b8..ceec9745 100644 --- a/Makefile +++ b/Makefile @@ -129,12 +129,22 @@ token-kubeconfig: ## Create a local ~/.kube/config with password (not usually ne # We only check the remote ssh git branch's existance if we're not running inside a container # as getting ssh auth working inside a container seems a bit brittle +# If the main repoUpstreamURL field is set, then we need to check against +# that and not target_repo .PHONY: validate-origin validate-origin: ## verify the git origin is available @echo "Checking repository:" - @echo -n " $(TARGET_REPO) - branch '$(TARGET_BRANCH)': " - @git ls-remote --exit-code --heads $(TARGET_REPO) $(TARGET_BRANCH) >/dev/null &&\ - echo "OK" || (echo "NOT FOUND"; exit 1) + $(eval UPSTREAMURL := $(shell yq -r '.main.git.repoUpstreamURL // (.main.git.repoUpstreamURL = "")' values-global.yaml)) + @if [ -z "$(UPSTREAMURL)" ]; then\ + echo -n " $(TARGET_REPO) - branch '$(TARGET_BRANCH)': ";\ + git ls-remote --exit-code --heads $(TARGET_REPO) $(TARGET_BRANCH) >/dev/null &&\ + echo "OK" || (echo "NOT FOUND"; exit 1);\ + else\ + echo "Upstream URL set to: $(UPSTREAMURL)";\ + echo -n " $(UPSTREAMURL) - branch '$(TARGET_BRANCH)': ";\ + git ls-remote --exit-code --heads $(UPSTREAMURL) $(TARGET_BRANCH) >/dev/null &&\ + echo "OK" || (echo "NOT FOUND"; exit 1);\ + fi .PHONY: validate-cluster validate-cluster: ## Do some cluster validations before installing From 8dfad491b7b616a0866d752e361935d526335382 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 15 Oct 2024 19:25:46 +0200 Subject: [PATCH 197/222] Make the make install output less daunting The current output is a bit daunting for first-time users as it outputs things like the following a few times: customresourcedefinition.apiextensions.k8s.io/patterns.gitops.hybrid-cloud-patterns.io created configmap/patterns-operator-config created subscription.operators.coreos.com/patterns-operator created error: resource mapping not found for name: "rhoai-patterns-demo" namespace: "openshift-operators" from "STDIN": no matches for kind "Pattern" in version "gitops.hybrid-cloud-patterns.io/v1alpha1" ensure CRDs are installed first Let's switch to something a bit more user-friendly: make -f common/Makefile operator-deploy make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Checking repository: https://github.com/mbaldessari/multicloud-gitops.git - branch 'luis-demo': OK Checking cluster: cluster-info: OK storageclass: WARNING: No storageclass found Installing pattern: Done ... Do some magic with file descriptors so we still manage to capture the helm template stderr and the oc apply stdout+stderr and output them at the end in case of failure. In such cases the output will be something like the following: Installing pattern: .....Installation failed [5/5]. Error: Pulled: quay.io/hybridcloudpatterns/pattern-install:0.0.3 Digest: sha256:dd2d35d462b75aa8358ff278757dca0ee3c878cadafa64df8c68f880b59569ef E1015 18:41:31.585465 196315 memcache.go:265] couldn't get current server API group list: Get "https://api.sno3.ocplab.ocp:6443/api?timeout=32s": tls: failed to verify certificate: x509: certificate signed by un known authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kube-apiserver-lb-signer") ... Suggested-by: Luis Tomas Bolivar --- Makefile | 6 +----- scripts/deploy-pattern.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100755 scripts/deploy-pattern.sh diff --git a/Makefile b/Makefile index a5c102b8..44a42228 100644 --- a/Makefile +++ b/Makefile @@ -68,11 +68,7 @@ preview-%: .PHONY: operator-deploy operator-deploy operator-upgrade: validate-prereq validate-origin validate-cluster ## runs helm install - @set -e -o pipefail - # Retry five times because the CRD might not be fully installed yet - for i in {1..5}; do \ - helm template --include-crds --name-template $(NAME) $(PATTERN_INSTALL_CHART) $(HELM_OPTS) | oc apply -f- && break || sleep 10; \ - done + @common/scripts/deploy-pattern.sh $(NAME) $(PATTERN_INSTALL_CHART) $(HELM_OPTS) .PHONY: uninstall uninstall: ## runs helm uninstall diff --git a/scripts/deploy-pattern.sh b/scripts/deploy-pattern.sh new file mode 100755 index 00000000..7393d9b6 --- /dev/null +++ b/scripts/deploy-pattern.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -o pipefail + +RUNS=5 +# Retry five times because the CRD might not be fully installed yet +echo -n "Installing pattern: " +for i in $(seq 1 ${RUNS}); do \ + exec 3>&1 4>&2 + OUT=$( { helm template --include-crds --name-template $* 2>&4 | oc apply -f- 2>&4 1>&3; } 4>&1 3>&1) + exec 3>&- 4>&- + ret=$? + if [ ${ret} -eq 0 ]; then + break; + else + echo -n "." + sleep 10 + fi +done + +# All the runs failed +if [ ${i} -eq ${RUNS} ]; then + echo "Installation failed [${i}/${RUNS}]. Error:" + echo "${OUT}" + exit 1 +fi +echo "Done" From c9f1fddbc7db2d2093c0e27dbab52b80767904d5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 22 Oct 2024 10:00:14 +0200 Subject: [PATCH 198/222] Record the exit code at the right time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise it records the exit code of the exec call which is always 0. This now makes things error out correctly whereas previously it did not: ❯ ./pattern.sh make install make -f common/Makefile operator-deploy make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Checking repository: https://github.com/mbaldessari/multicloud-gitops.git - branch 'debug': OK Checking cluster: cluster-info: OK storageclass: OK Installing pattern: .....Installation failed [5/5]. Error: Pulled: quay.io/rhn_support_mbaldess/pattern-install:0.0.4 Digest: sha256:6a5431d257f4bf05d6ac91bca4f4aa010ecb1ee60d2e03c1d0984835d210a0a8 customresourcedefinition.apiextensions.k8s.io/patterns.gitops.hybrid-cloud-patterns.io unchanged configmap/patterns-operator-config unchanged resource mapping not found for name: "patterns-operator" namespace: "openshift-operators" from "STDIN": no matches for kind "SubscriptionNotexistant" in version "operators.coreos.com/v1alpha1" ensure CRDs are installed first Error from server (NotFound): error when creating "STDIN": namespaces "openshift-operators-notexistant" not found make[1]: *** [common/Makefile:71: operator-deploy] Error 1 make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make: *** [Makefile:12: operator-deploy] Error 2 --- scripts/deploy-pattern.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/deploy-pattern.sh b/scripts/deploy-pattern.sh index 7393d9b6..56837366 100755 --- a/scripts/deploy-pattern.sh +++ b/scripts/deploy-pattern.sh @@ -7,8 +7,8 @@ echo -n "Installing pattern: " for i in $(seq 1 ${RUNS}); do \ exec 3>&1 4>&2 OUT=$( { helm template --include-crds --name-template $* 2>&4 | oc apply -f- 2>&4 1>&3; } 4>&1 3>&1) - exec 3>&- 4>&- ret=$? + exec 3>&- 4>&- if [ ${ret} -eq 0 ]; then break; else From 9a24f6fcfc28227ada119bf4d1d389808e146fa9 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 25 Nov 2024 12:08:02 +0100 Subject: [PATCH 199/222] Fix path when invoking the qe run_test.sh script --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fef82fd1..20e543fc 100644 --- a/Makefile +++ b/Makefile @@ -214,7 +214,7 @@ argo-healthcheck: ## Checks if all argo applications are synced .PHONY: qe-tests qe-tests: ## Runs the tests that QE runs @set -e; if [ -f ./tests/interop/run_tests.sh ]; then \ - ./tests/interop/run_tests.sh; \ + pushd ./tests/interop; ./run_tests.sh; popd; \ else \ echo "No ./tests/interop/run_tests.sh found skipping"; \ fi From 0d9d51ad7198e22edbf23cfddcac7f8835aac31e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 19 Dec 2024 13:47:14 +0100 Subject: [PATCH 200/222] Add a warning when pattern folder and pattern name differ Co-Authored-By: Akos Eros --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index 20e543fc..37984d1e 100644 --- a/Makefile +++ b/Makefile @@ -164,6 +164,13 @@ validate-schema: ## validates values files against schema in common/clustergroup .PHONY: validate-prereq validate-prereq: ## verify pre-requisites + $(eval GLOBAL_PATTERN := $(shell yq -r .global.pattern values-global.yaml)) + @if [ $(NAME) != $(GLOBAL_PATTERN) ]; then\ + echo "";\ + echo "WARNING: folder directory is \"$(NAME)\" and global.pattern is set to \"$(GLOBAL_PATTERN)\"";\ + echo "this can create problems. Please make sure they are the same!";\ + echo "";\ + fi @if [ ! -f /run/.containerenv ]; then\ echo "Checking prerequisites:";\ for t in $(EXECUTABLES); do if ! which $$t > /dev/null 2>&1; then echo "No $$t in PATH"; exit 1; fi; done;\ From 0cc13f6d9f41330516118c7fc4650b54e195a130 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 19 Dec 2024 13:48:16 +0100 Subject: [PATCH 201/222] Drop some old and unused prereq test --- Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Makefile b/Makefile index 37984d1e..1be6bbf3 100644 --- a/Makefile +++ b/Makefile @@ -173,8 +173,6 @@ validate-prereq: ## verify pre-requisites fi @if [ ! -f /run/.containerenv ]; then\ echo "Checking prerequisites:";\ - for t in $(EXECUTABLES); do if ! which $$t > /dev/null 2>&1; then echo "No $$t in PATH"; exit 1; fi; done;\ - echo " Check for '$(EXECUTABLES)': OK";\ echo -n " Check for python-kubernetes: ";\ if ! ansible -m ansible.builtin.command -a "{{ ansible_python_interpreter }} -c 'import kubernetes'" localhost > /dev/null 2>&1; then echo "Not found"; exit 1; fi;\ echo "OK";\ From 5063467592e97e9a5cbd10e5399a9f0c23a6dee3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 7 Jan 2025 17:56:28 +0100 Subject: [PATCH 202/222] Fix validated-schema make target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the slimming of common this won't work anymore: ❯ make validate-schema make -f common/Makefile validate-schema make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Validating clustergroup schema of: ./values-global.yamlError: repo common not found make[1]: *** [common/Makefile:162: validate-schema] Error 1 make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make: *** [Makefile:12: validate-schema] Error 2 Fix this to use the oci helm chart: ❯ make validate-schema make -f common/Makefile validate-schema make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Validating clustergroup schema of: ./values-global.yamlPulled: quay.io/hybridcloudpatterns/clustergroup:0.9.13 Digest: sha256:725af54c0a5ad8c2235676bbff2785ece62c9929ab58aaf33837aa3f19708ce6 ./values-group-one.yamlPulled: quay.io/hybridcloudpatterns/clustergroup:0.9.13 Digest: sha256:725af54c0a5ad8c2235676bbff2785ece62c9929ab58aaf33837aa3f19708ce6 ./values-hub.yamlPulled: quay.io/hybridcloudpatterns/clustergroup:0.9.13 Digest: sha256:725af54c0a5ad8c2235676bbff2785ece62c9929ab58aaf33837aa3f19708ce6 make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1be6bbf3..53e15d3f 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,7 @@ validate-cluster: ## Do some cluster validations before installing validate-schema: ## validates values files against schema in common/clustergroup $(eval VAL_PARAMS := $(shell for i in ./values-*.yaml; do echo -n "$${i} "; done)) @echo -n "Validating clustergroup schema of: " - @set -e; for i in $(VAL_PARAMS); do echo -n " $$i"; helm template common/clustergroup $(HELM_OPTS) -f "$${i}" >/dev/null; done + @set -e; for i in $(VAL_PARAMS); do echo -n " $$i"; helm template oci://quay.io/hybridcloudpatterns/clustergroup $(HELM_OPTS) -f "$${i}" >/dev/null; done @echo .PHONY: validate-prereq From 250c154582b91a443450bc46c7d347f7900cb23e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 14 Jan 2025 20:40:19 +0100 Subject: [PATCH 203/222] Wait some more before giving up Yukin observed a case on a baremetal server where the install failed with: make -f common/Makefile operator-deploy make[1]: Entering directory '/home/fedora/validated_patterns/multicloud-gitops' Checking repository: https://github.com/validatedpatterns-workspace/multicloud-gitops - branch 'qe_test-18760': OK Checking cluster: cluster-info: OK storageclass: OK Installing pattern: ....Installation failed [5/5]. Error: WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/fedora/rhvpsno2-intel-18760/auth/kubeconfig WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/fedora/rhvpsno2-intel-18760/auth/kubeconfig Pulled: quay.io/hybridcloudpatterns/pattern-install:0.0.7 Digest: sha256:b845f86c735478cfd44b0b43842697851cec64737c737bd18a872fa86bb0484d customresourcedefinition.apiextensions.k8s.io/patterns.gitops.hybrid-cloud-patterns.io unchanged configmap/patterns-operator-config unchanged pattern.gitops.hybrid-cloud-patterns.io/multicloud-gitops created subscription.operators.coreos.com/patterns-operator unchanged make[1]: *** [common/Makefile:71: operator-deploy] Error 1 make[1]: Leaving directory '/home/fedora/validated_patterns/multicloud-gitops' make: *** [Makefile:12: operator-deploy] Error 2 In fact the install proceeded just okay, we just gave up too early. Let's double the amount of times we wait for this and also increase the wait in between tries by 5 seconds. Hopefully this should cover these edge cases. --- scripts/deploy-pattern.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/deploy-pattern.sh b/scripts/deploy-pattern.sh index 56837366..61074fe1 100755 --- a/scripts/deploy-pattern.sh +++ b/scripts/deploy-pattern.sh @@ -1,7 +1,8 @@ #!/bin/bash set -o pipefail -RUNS=5 +RUNS=10 +WAIT=15 # Retry five times because the CRD might not be fully installed yet echo -n "Installing pattern: " for i in $(seq 1 ${RUNS}); do \ @@ -13,7 +14,7 @@ for i in $(seq 1 ${RUNS}); do \ break; else echo -n "." - sleep 10 + sleep "${WAIT}" fi done From cc36e1f879f7d47ed9c8ae9be855d04fc3f98449 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 22 Jan 2025 17:14:48 +0100 Subject: [PATCH 204/222] Fix argo-healthcheck target If ACM is installed the search for `applications` matches the ACM one and not the argo one. --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 53e15d3f..fc10236e 100644 --- a/Makefile +++ b/Makefile @@ -193,16 +193,16 @@ validate-prereq: ## verify pre-requisites .PHONY: argo-healthcheck argo-healthcheck: ## Checks if all argo applications are synced @echo "Checking argo applications" - $(eval APPS := $(shell oc get applications -A -o jsonpath='{range .items[*]}{@.metadata.namespace}{","}{@.metadata.name}{"\n"}{end}')) + $(eval APPS := $(shell oc get applications.argoproj.io -A -o jsonpath='{range .items[*]}{@.metadata.namespace}{","}{@.metadata.name}{"\n"}{end}')) @NOTOK=0; \ for i in $(APPS); do\ n=`echo "$${i}" | cut -f1 -d,`;\ a=`echo "$${i}" | cut -f2 -d,`;\ - STATUS=`oc get -n "$${n}" application/"$${a}" -o jsonpath='{.status.sync.status}'`;\ + STATUS=`oc get -n "$${n}" applications.argoproj.io/"$${a}" -o jsonpath='{.status.sync.status}'`;\ if [[ $$STATUS != "Synced" ]]; then\ NOTOK=$$(( $${NOTOK} + 1));\ fi;\ - HEALTH=`oc get -n "$${n}" application/"$${a}" -o jsonpath='{.status.health.status}'`;\ + HEALTH=`oc get -n "$${n}" applications.argoproj.io/"$${a}" -o jsonpath='{.status.health.status}'`;\ if [[ $$HEALTH != "Healthy" ]]; then\ NOTOK=$$(( $${NOTOK} + 1));\ fi;\ From e3e7add390b9e8c071be6ea8028fd790a1f2d052 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Feb 2025 21:25:55 +0100 Subject: [PATCH 205/222] Push TARGET_SITE into the in-container variables This way we can override the TARGET_SITE when invoking pattern.sh --- scripts/pattern-util.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 1fcaee76..d04ea05d 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -85,6 +85,7 @@ podman run -it --rm --pull=newer \ -e EXTRA_HELM_OPTS \ -e EXTRA_PLAYBOOK_OPTS \ -e TARGET_ORIGIN \ + -e TARGET_SITE \ -e NAME \ -e TOKEN_SECRET \ -e TOKEN_NAMESPACE \ From 0746c6e77c8d5c405e99dd10b1ae9fffedda1d9c Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Feb 2025 11:49:02 +0100 Subject: [PATCH 206/222] Do not bind mount /etc/pki blindly Since ubuntu sometimes has /etc/pki/fwupd with little else in there, let's just bind mount /etc/pki when /etc/pki/tls exists. This keeps Fedora-based distros running and should fix this specific corner case observed on ubuntu. Co-Authored-By: Akos Eros Closes: https://github.com/validatedpatterns/medical-diagnosis/issues/130 --- scripts/pattern-util.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index d04ea05d..27b30229 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -64,8 +64,10 @@ fi # if we are using podman machine then we do not bind mount anything (for now!) REMOTE_PODMAN=$(podman system connection list -q | wc -l) if [ $REMOTE_PODMAN -eq 0 ]; then # If we are not using podman machine we check the hosts folders - # Use /etc/pki by default and try a couple of fallbacks if it does not exist - if [ -d /etc/pki ]; then + # We check /etc/pki/tls because on ubuntu /etc/pki/fwupd sometimes + # exists but not /etc/pki/tls and we do not want to bind mount in such a case + # as it would find no certificates at all. + if [ -d /etc/pki/tls ]; then PKI_HOST_MOUNT_ARGS="-v /etc/pki:/etc/pki:ro" elif [ -d /etc/ssl ]; then PKI_HOST_MOUNT_ARGS="-v /etc/ssl:/etc/ssl:ro" From f85286f4d08b42833bd5906d73ba835b4c2e87c6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 8 Feb 2025 11:51:44 +0100 Subject: [PATCH 207/222] Switch to multisource charts --- values-global.yaml | 1 + values-hub.yaml | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/values-global.yaml b/values-global.yaml index 75c73f9a..32988e19 100644 --- a/values-global.yaml +++ b/values-global.yaml @@ -16,3 +16,4 @@ main: clusterGroupName: hub multiSourceConfig: enabled: true + clusterGroupChartVersion: 0.9.* diff --git a/values-hub.yaml b/values-hub.yaml index 28f43141..cb19dce4 100644 --- a/values-hub.yaml +++ b/values-hub.yaml @@ -81,12 +81,14 @@ clusterGroup: name: vault namespace: vault project: hub - path: common/hashicorp-vault + chart: hashicorp-vault + chartVersion: 0.1.* golang-external-secrets: name: golang-external-secrets namespace: golang-external-secrets project: hub - path: common/golang-external-secrets + chart: golang-external-secrets + chartVersion: 0.1.* minio: name: minio namespace: rag-llm @@ -153,7 +155,7 @@ clusterGroup: jobs: - name: hello-world # ansible playbook to be run - playbook: common/ansible/playbooks/hello-world/hello-world.yaml + playbook: rhvp.cluster_utils.hello_world # per playbook timeout in seconds timeout: 234 # verbosity: "-v" From 4e4eb472df60ac7b3d24783dbfb67506adbecd1c Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 8 Feb 2025 12:54:47 +0100 Subject: [PATCH 208/222] Drop old test diffs --- ...demo-industrial-edge-factory.expected.yaml | 161 - ...fig-demo-industrial-edge-hub.expected.yaml | 161 - ...g-demo-medical-diagnosis-hub.expected.yaml | 161 - tests/all-config-demo-naked.expected.yaml | 161 - tests/all-config-demo-normal.expected.yaml | 161 - ...orld-industrial-edge-factory.expected.yaml | 120 - ...lo-world-industrial-edge-hub.expected.yaml | 120 - ...-world-medical-diagnosis-hub.expected.yaml | 120 - tests/all-hello-world-naked.expected.yaml | 120 - tests/all-hello-world-normal.expected.yaml | 120 - ...-acm-industrial-edge-factory.expected.yaml | 111 - ...mmon-acm-industrial-edge-hub.expected.yaml | 318 - ...on-acm-medical-diagnosis-hub.expected.yaml | 309 - tests/common-acm-naked.expected.yaml | 112 - tests/common-acm-normal.expected.yaml | 808 -- ...roup-industrial-edge-factory.expected.yaml | 773 - ...tergroup-industrial-edge-hub.expected.yaml | 1590 --- ...rgroup-medical-diagnosis-hub.expected.yaml | 1669 --- tests/common-clustergroup-naked.expected.yaml | 405 - .../common-clustergroup-normal.expected.yaml | 1169 -- .../common-examples-blank-naked.expected.yaml | 6 - ...common-examples-blank-normal.expected.yaml | 6 - ...les-kustomize-renderer-naked.expected.yaml | 36 - ...es-kustomize-renderer-normal.expected.yaml | 36 - ...rets-industrial-edge-factory.expected.yaml | 11835 ---------------- ...-secrets-industrial-edge-hub.expected.yaml | 11835 ---------------- ...ecrets-medical-diagnosis-hub.expected.yaml | 11835 ---------------- ...olang-external-secrets-naked.expected.yaml | 11835 ---------------- ...lang-external-secrets-normal.expected.yaml | 11835 ---------------- ...ault-industrial-edge-factory.expected.yaml | 408 - ...rp-vault-industrial-edge-hub.expected.yaml | 408 - ...-vault-medical-diagnosis-hub.expected.yaml | 408 - ...common-hashicorp-vault-naked.expected.yaml | 408 - ...ommon-hashicorp-vault-normal.expected.yaml | 408 - ...tall-industrial-edge-factory.expected.yaml | 66 - ...-install-industrial-edge-hub.expected.yaml | 66 - ...nstall-medical-diagnosis-hub.expected.yaml | 66 - tests/common-install-naked.expected.yaml | 66 - tests/common-install-normal.expected.yaml | 66 - ...rypt-industrial-edge-factory.expected.yaml | 202 - ...sencrypt-industrial-edge-hub.expected.yaml | 202 - ...ncrypt-medical-diagnosis-hub.expected.yaml | 202 - tests/common-letsencrypt-naked.expected.yaml | 202 - tests/common-letsencrypt-normal.expected.yaml | 202 - ...tall-industrial-edge-factory.expected.yaml | 47 - ...-install-industrial-edge-hub.expected.yaml | 47 - ...nstall-medical-diagnosis-hub.expected.yaml | 47 - ...ommon-operator-install-naked.expected.yaml | 47 - ...mmon-operator-install-normal.expected.yaml | 47 - 49 files changed, 71543 deletions(-) delete mode 100644 tests/all-config-demo-industrial-edge-factory.expected.yaml delete mode 100644 tests/all-config-demo-industrial-edge-hub.expected.yaml delete mode 100644 tests/all-config-demo-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/all-config-demo-naked.expected.yaml delete mode 100644 tests/all-config-demo-normal.expected.yaml delete mode 100644 tests/all-hello-world-industrial-edge-factory.expected.yaml delete mode 100644 tests/all-hello-world-industrial-edge-hub.expected.yaml delete mode 100644 tests/all-hello-world-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/all-hello-world-naked.expected.yaml delete mode 100644 tests/all-hello-world-normal.expected.yaml delete mode 100644 tests/common-acm-industrial-edge-factory.expected.yaml delete mode 100644 tests/common-acm-industrial-edge-hub.expected.yaml delete mode 100644 tests/common-acm-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/common-acm-naked.expected.yaml delete mode 100644 tests/common-acm-normal.expected.yaml delete mode 100644 tests/common-clustergroup-industrial-edge-factory.expected.yaml delete mode 100644 tests/common-clustergroup-industrial-edge-hub.expected.yaml delete mode 100644 tests/common-clustergroup-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/common-clustergroup-naked.expected.yaml delete mode 100644 tests/common-clustergroup-normal.expected.yaml delete mode 100644 tests/common-examples-blank-naked.expected.yaml delete mode 100644 tests/common-examples-blank-normal.expected.yaml delete mode 100644 tests/common-examples-kustomize-renderer-naked.expected.yaml delete mode 100644 tests/common-examples-kustomize-renderer-normal.expected.yaml delete mode 100644 tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml delete mode 100644 tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml delete mode 100644 tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/common-golang-external-secrets-naked.expected.yaml delete mode 100644 tests/common-golang-external-secrets-normal.expected.yaml delete mode 100644 tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml delete mode 100644 tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml delete mode 100644 tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/common-hashicorp-vault-naked.expected.yaml delete mode 100644 tests/common-hashicorp-vault-normal.expected.yaml delete mode 100644 tests/common-install-industrial-edge-factory.expected.yaml delete mode 100644 tests/common-install-industrial-edge-hub.expected.yaml delete mode 100644 tests/common-install-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/common-install-naked.expected.yaml delete mode 100644 tests/common-install-normal.expected.yaml delete mode 100644 tests/common-letsencrypt-industrial-edge-factory.expected.yaml delete mode 100644 tests/common-letsencrypt-industrial-edge-hub.expected.yaml delete mode 100644 tests/common-letsencrypt-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/common-letsencrypt-naked.expected.yaml delete mode 100644 tests/common-letsencrypt-normal.expected.yaml delete mode 100644 tests/common-operator-install-industrial-edge-factory.expected.yaml delete mode 100644 tests/common-operator-install-industrial-edge-hub.expected.yaml delete mode 100644 tests/common-operator-install-medical-diagnosis-hub.expected.yaml delete mode 100644 tests/common-operator-install-naked.expected.yaml delete mode 100644 tests/common-operator-install-normal.expected.yaml diff --git a/tests/all-config-demo-industrial-edge-factory.expected.yaml b/tests/all-config-demo-industrial-edge-factory.expected.yaml deleted file mode 100644 index 3f45295a..00000000 --- a/tests/all-config-demo-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,161 +0,0 @@ ---- -# Source: config-demo/templates/config-demo-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: config-demo-configmap - labels: - app.kubernetes.io/instance: config-demo -data: - "index.html": |- - - - - - Config Demo - - -

- Hub Cluster domain is 'apps.hub.example.com'
- Pod is running on Local Cluster Domain 'apps.region.example.com'
-

-

- The secret is secret -

- - ---- -# Source: config-demo/templates/config-demo-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: config-demo - name: config-demo -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: config-demo - deploymentconfig: config-demo - sessionAffinity: None - type: ClusterIP ---- -# Source: config-demo/templates/config-demo-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: config-demo - name: config-demo -spec: - replicas: 2 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: config-demo - template: - metadata: - creationTimestamp: null - labels: - app: config-demo - deploymentconfig: config-demo - name: config-demo - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: config-demo-configmap - - mountPath: /var/www/html/secret - readOnly: true - name: config-demo-secret - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: config-demo-configmap - configMap: - defaultMode: 438 - name: config-demo-configmap - - name: config-demo-secret - secret: - secretName: config-demo-secret ---- -# Source: config-demo/templates/config-demo-external-secret.yaml -apiVersion: "external-secrets.io/v1beta1" -kind: ExternalSecret -metadata: - name: config-demo-secret - namespace: config-demo -spec: - refreshInterval: 15s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: config-demo-secret - template: - type: Opaque - dataFrom: - - extract: - key: secret/data/global/config-demo ---- -# Source: config-demo/templates/config-demo-is.yaml -apiVersion: image.openshift.io/v1 -kind: ImageStream -metadata: - name: config-demo -spec: - lookupPolicy: - local: true - tags: - - name: registry.access.redhat.com/ubi8/httpd-24 - importPolicy: {} - referencePolicy: - type: Local ---- -# Source: config-demo/templates/config-demo-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: config-demo - name: config-demo -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: config-demo - weight: 100 - wildcardPolicy: None diff --git a/tests/all-config-demo-industrial-edge-hub.expected.yaml b/tests/all-config-demo-industrial-edge-hub.expected.yaml deleted file mode 100644 index 3f45295a..00000000 --- a/tests/all-config-demo-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,161 +0,0 @@ ---- -# Source: config-demo/templates/config-demo-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: config-demo-configmap - labels: - app.kubernetes.io/instance: config-demo -data: - "index.html": |- - - - - - Config Demo - - -

- Hub Cluster domain is 'apps.hub.example.com'
- Pod is running on Local Cluster Domain 'apps.region.example.com'
-

-

- The secret is secret -

- - ---- -# Source: config-demo/templates/config-demo-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: config-demo - name: config-demo -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: config-demo - deploymentconfig: config-demo - sessionAffinity: None - type: ClusterIP ---- -# Source: config-demo/templates/config-demo-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: config-demo - name: config-demo -spec: - replicas: 2 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: config-demo - template: - metadata: - creationTimestamp: null - labels: - app: config-demo - deploymentconfig: config-demo - name: config-demo - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: config-demo-configmap - - mountPath: /var/www/html/secret - readOnly: true - name: config-demo-secret - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: config-demo-configmap - configMap: - defaultMode: 438 - name: config-demo-configmap - - name: config-demo-secret - secret: - secretName: config-demo-secret ---- -# Source: config-demo/templates/config-demo-external-secret.yaml -apiVersion: "external-secrets.io/v1beta1" -kind: ExternalSecret -metadata: - name: config-demo-secret - namespace: config-demo -spec: - refreshInterval: 15s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: config-demo-secret - template: - type: Opaque - dataFrom: - - extract: - key: secret/data/global/config-demo ---- -# Source: config-demo/templates/config-demo-is.yaml -apiVersion: image.openshift.io/v1 -kind: ImageStream -metadata: - name: config-demo -spec: - lookupPolicy: - local: true - tags: - - name: registry.access.redhat.com/ubi8/httpd-24 - importPolicy: {} - referencePolicy: - type: Local ---- -# Source: config-demo/templates/config-demo-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: config-demo - name: config-demo -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: config-demo - weight: 100 - wildcardPolicy: None diff --git a/tests/all-config-demo-medical-diagnosis-hub.expected.yaml b/tests/all-config-demo-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index 3f45295a..00000000 --- a/tests/all-config-demo-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,161 +0,0 @@ ---- -# Source: config-demo/templates/config-demo-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: config-demo-configmap - labels: - app.kubernetes.io/instance: config-demo -data: - "index.html": |- - - - - - Config Demo - - -

- Hub Cluster domain is 'apps.hub.example.com'
- Pod is running on Local Cluster Domain 'apps.region.example.com'
-

-

- The secret is secret -

- - ---- -# Source: config-demo/templates/config-demo-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: config-demo - name: config-demo -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: config-demo - deploymentconfig: config-demo - sessionAffinity: None - type: ClusterIP ---- -# Source: config-demo/templates/config-demo-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: config-demo - name: config-demo -spec: - replicas: 2 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: config-demo - template: - metadata: - creationTimestamp: null - labels: - app: config-demo - deploymentconfig: config-demo - name: config-demo - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: config-demo-configmap - - mountPath: /var/www/html/secret - readOnly: true - name: config-demo-secret - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: config-demo-configmap - configMap: - defaultMode: 438 - name: config-demo-configmap - - name: config-demo-secret - secret: - secretName: config-demo-secret ---- -# Source: config-demo/templates/config-demo-external-secret.yaml -apiVersion: "external-secrets.io/v1beta1" -kind: ExternalSecret -metadata: - name: config-demo-secret - namespace: config-demo -spec: - refreshInterval: 15s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: config-demo-secret - template: - type: Opaque - dataFrom: - - extract: - key: secret/data/global/config-demo ---- -# Source: config-demo/templates/config-demo-is.yaml -apiVersion: image.openshift.io/v1 -kind: ImageStream -metadata: - name: config-demo -spec: - lookupPolicy: - local: true - tags: - - name: registry.access.redhat.com/ubi8/httpd-24 - importPolicy: {} - referencePolicy: - type: Local ---- -# Source: config-demo/templates/config-demo-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: config-demo - name: config-demo -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: config-demo - weight: 100 - wildcardPolicy: None diff --git a/tests/all-config-demo-naked.expected.yaml b/tests/all-config-demo-naked.expected.yaml deleted file mode 100644 index 8887a3ba..00000000 --- a/tests/all-config-demo-naked.expected.yaml +++ /dev/null @@ -1,161 +0,0 @@ ---- -# Source: config-demo/templates/config-demo-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: config-demo-configmap - labels: - app.kubernetes.io/instance: config-demo -data: - "index.html": |- - - - - - Config Demo - - -

- Hub Cluster domain is 'hub.example.com'
- Pod is running on Local Cluster Domain 'region-one.example.com'
-

-

- The secret is secret -

- - ---- -# Source: config-demo/templates/config-demo-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: config-demo - name: config-demo -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: config-demo - deploymentconfig: config-demo - sessionAffinity: None - type: ClusterIP ---- -# Source: config-demo/templates/config-demo-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: config-demo - name: config-demo -spec: - replicas: 2 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: config-demo - template: - metadata: - creationTimestamp: null - labels: - app: config-demo - deploymentconfig: config-demo - name: config-demo - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: config-demo-configmap - - mountPath: /var/www/html/secret - readOnly: true - name: config-demo-secret - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: config-demo-configmap - configMap: - defaultMode: 438 - name: config-demo-configmap - - name: config-demo-secret - secret: - secretName: config-demo-secret ---- -# Source: config-demo/templates/config-demo-external-secret.yaml -apiVersion: "external-secrets.io/v1beta1" -kind: ExternalSecret -metadata: - name: config-demo-secret - namespace: config-demo -spec: - refreshInterval: 15s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: config-demo-secret - template: - type: Opaque - dataFrom: - - extract: - key: secret/data/global/config-demo ---- -# Source: config-demo/templates/config-demo-is.yaml -apiVersion: image.openshift.io/v1 -kind: ImageStream -metadata: - name: config-demo -spec: - lookupPolicy: - local: true - tags: - - name: registry.access.redhat.com/ubi8/httpd-24 - importPolicy: {} - referencePolicy: - type: Local ---- -# Source: config-demo/templates/config-demo-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: config-demo - name: config-demo -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: config-demo - weight: 100 - wildcardPolicy: None diff --git a/tests/all-config-demo-normal.expected.yaml b/tests/all-config-demo-normal.expected.yaml deleted file mode 100644 index 3f45295a..00000000 --- a/tests/all-config-demo-normal.expected.yaml +++ /dev/null @@ -1,161 +0,0 @@ ---- -# Source: config-demo/templates/config-demo-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: config-demo-configmap - labels: - app.kubernetes.io/instance: config-demo -data: - "index.html": |- - - - - - Config Demo - - -

- Hub Cluster domain is 'apps.hub.example.com'
- Pod is running on Local Cluster Domain 'apps.region.example.com'
-

-

- The secret is secret -

- - ---- -# Source: config-demo/templates/config-demo-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: config-demo - name: config-demo -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: config-demo - deploymentconfig: config-demo - sessionAffinity: None - type: ClusterIP ---- -# Source: config-demo/templates/config-demo-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: config-demo - name: config-demo -spec: - replicas: 2 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: config-demo - template: - metadata: - creationTimestamp: null - labels: - app: config-demo - deploymentconfig: config-demo - name: config-demo - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: config-demo-configmap - - mountPath: /var/www/html/secret - readOnly: true - name: config-demo-secret - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: config-demo-configmap - configMap: - defaultMode: 438 - name: config-demo-configmap - - name: config-demo-secret - secret: - secretName: config-demo-secret ---- -# Source: config-demo/templates/config-demo-external-secret.yaml -apiVersion: "external-secrets.io/v1beta1" -kind: ExternalSecret -metadata: - name: config-demo-secret - namespace: config-demo -spec: - refreshInterval: 15s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: config-demo-secret - template: - type: Opaque - dataFrom: - - extract: - key: secret/data/global/config-demo ---- -# Source: config-demo/templates/config-demo-is.yaml -apiVersion: image.openshift.io/v1 -kind: ImageStream -metadata: - name: config-demo -spec: - lookupPolicy: - local: true - tags: - - name: registry.access.redhat.com/ubi8/httpd-24 - importPolicy: {} - referencePolicy: - type: Local ---- -# Source: config-demo/templates/config-demo-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: config-demo - name: config-demo -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: config-demo - weight: 100 - wildcardPolicy: None diff --git a/tests/all-hello-world-industrial-edge-factory.expected.yaml b/tests/all-hello-world-industrial-edge-factory.expected.yaml deleted file mode 100644 index daade8e6..00000000 --- a/tests/all-hello-world-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,120 +0,0 @@ ---- -# Source: hello-world/templates/hello-world-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hello-world-configmap - labels: - app.kubernetes.io/instance: hello-world -data: - "index.html": |- - - - - - Hello World - - -

Hello World!

-
-

- Hub Cluster domain is 'apps.hub.example.com'
- Pod is running on Local Cluster Domain 'apps.region.example.com'
-

- - ---- -# Source: hello-world/templates/hello-world-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: hello-world - name: hello-world -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: hello-world - deploymentconfig: hello-world - sessionAffinity: None - type: ClusterIP ---- -# Source: hello-world/templates/hello-world-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: hello-world - name: hello-world -spec: - replicas: 1 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: hello-world - template: - metadata: - labels: - app: hello-world - deploymentconfig: hello-world - name: hello-world - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: hello-world-configmap - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: hello-world-configmap - configMap: - defaultMode: 438 - name: hello-world-configmap ---- -# Source: hello-world/templates/hello-world-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: hello-world - name: hello-world -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: hello-world - weight: 100 - wildcardPolicy: None diff --git a/tests/all-hello-world-industrial-edge-hub.expected.yaml b/tests/all-hello-world-industrial-edge-hub.expected.yaml deleted file mode 100644 index daade8e6..00000000 --- a/tests/all-hello-world-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,120 +0,0 @@ ---- -# Source: hello-world/templates/hello-world-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hello-world-configmap - labels: - app.kubernetes.io/instance: hello-world -data: - "index.html": |- - - - - - Hello World - - -

Hello World!

-
-

- Hub Cluster domain is 'apps.hub.example.com'
- Pod is running on Local Cluster Domain 'apps.region.example.com'
-

- - ---- -# Source: hello-world/templates/hello-world-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: hello-world - name: hello-world -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: hello-world - deploymentconfig: hello-world - sessionAffinity: None - type: ClusterIP ---- -# Source: hello-world/templates/hello-world-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: hello-world - name: hello-world -spec: - replicas: 1 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: hello-world - template: - metadata: - labels: - app: hello-world - deploymentconfig: hello-world - name: hello-world - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: hello-world-configmap - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: hello-world-configmap - configMap: - defaultMode: 438 - name: hello-world-configmap ---- -# Source: hello-world/templates/hello-world-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: hello-world - name: hello-world -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: hello-world - weight: 100 - wildcardPolicy: None diff --git a/tests/all-hello-world-medical-diagnosis-hub.expected.yaml b/tests/all-hello-world-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index daade8e6..00000000 --- a/tests/all-hello-world-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,120 +0,0 @@ ---- -# Source: hello-world/templates/hello-world-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hello-world-configmap - labels: - app.kubernetes.io/instance: hello-world -data: - "index.html": |- - - - - - Hello World - - -

Hello World!

-
-

- Hub Cluster domain is 'apps.hub.example.com'
- Pod is running on Local Cluster Domain 'apps.region.example.com'
-

- - ---- -# Source: hello-world/templates/hello-world-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: hello-world - name: hello-world -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: hello-world - deploymentconfig: hello-world - sessionAffinity: None - type: ClusterIP ---- -# Source: hello-world/templates/hello-world-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: hello-world - name: hello-world -spec: - replicas: 1 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: hello-world - template: - metadata: - labels: - app: hello-world - deploymentconfig: hello-world - name: hello-world - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: hello-world-configmap - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: hello-world-configmap - configMap: - defaultMode: 438 - name: hello-world-configmap ---- -# Source: hello-world/templates/hello-world-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: hello-world - name: hello-world -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: hello-world - weight: 100 - wildcardPolicy: None diff --git a/tests/all-hello-world-naked.expected.yaml b/tests/all-hello-world-naked.expected.yaml deleted file mode 100644 index 4fc914cf..00000000 --- a/tests/all-hello-world-naked.expected.yaml +++ /dev/null @@ -1,120 +0,0 @@ ---- -# Source: hello-world/templates/hello-world-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hello-world-configmap - labels: - app.kubernetes.io/instance: hello-world -data: - "index.html": |- - - - - - Hello World - - -

Hello World!

-
-

- Hub Cluster domain is 'hub.example.com'
- Pod is running on Local Cluster Domain ''
-

- - ---- -# Source: hello-world/templates/hello-world-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: hello-world - name: hello-world -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: hello-world - deploymentconfig: hello-world - sessionAffinity: None - type: ClusterIP ---- -# Source: hello-world/templates/hello-world-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: hello-world - name: hello-world -spec: - replicas: 1 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: hello-world - template: - metadata: - labels: - app: hello-world - deploymentconfig: hello-world - name: hello-world - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: hello-world-configmap - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: hello-world-configmap - configMap: - defaultMode: 438 - name: hello-world-configmap ---- -# Source: hello-world/templates/hello-world-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: hello-world - name: hello-world -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: hello-world - weight: 100 - wildcardPolicy: None diff --git a/tests/all-hello-world-normal.expected.yaml b/tests/all-hello-world-normal.expected.yaml deleted file mode 100644 index daade8e6..00000000 --- a/tests/all-hello-world-normal.expected.yaml +++ /dev/null @@ -1,120 +0,0 @@ ---- -# Source: hello-world/templates/hello-world-cm.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: hello-world-configmap - labels: - app.kubernetes.io/instance: hello-world -data: - "index.html": |- - - - - - Hello World - - -

Hello World!

-
-

- Hub Cluster domain is 'apps.hub.example.com'
- Pod is running on Local Cluster Domain 'apps.region.example.com'
-

- - ---- -# Source: hello-world/templates/hello-world-svc.yaml -apiVersion: v1 -kind: Service -metadata: - labels: - app: hello-world - name: hello-world -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: hello-world - deploymentconfig: hello-world - sessionAffinity: None - type: ClusterIP ---- -# Source: hello-world/templates/hello-world-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: hello-world - name: hello-world -spec: - replicas: 1 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: hello-world - template: - metadata: - labels: - app: hello-world - deploymentconfig: hello-world - name: hello-world - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: hello-world-configmap - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: hello-world-configmap - configMap: - defaultMode: 438 - name: hello-world-configmap ---- -# Source: hello-world/templates/hello-world-route.yaml -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: hello-world - name: hello-world -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: hello-world - weight: 100 - wildcardPolicy: None diff --git a/tests/common-acm-industrial-edge-factory.expected.yaml b/tests/common-acm-industrial-edge-factory.expected.yaml deleted file mode 100644 index 66c0c0b9..00000000 --- a/tests/common-acm-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,111 +0,0 @@ ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" -spec: {} ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.11 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" diff --git a/tests/common-acm-industrial-edge-hub.expected.yaml b/tests/common-acm-industrial-edge-hub.expected.yaml deleted file mode 100644 index 07593017..00000000 --- a/tests/common-acm-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,318 +0,0 @@ ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-hub-ca-policy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-hub-ca-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-hub-ca-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: factory-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: factory-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: factory-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-hub-ca-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: factory-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: { - "matchExpressions": [ - { - "key": "vendor", - "operator": "In", - "values": [ - "OpenShift" - ] - } - ], - "matchLabels": { - "clusterGroup": "factory" - } -} ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-hub-ca-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-hub-ca-config-policy - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: hub-ca - namespace: imperative - data: - hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' - hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: factory-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: factory-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: mypattern-factory - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-factory.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-factory.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - - name: global.clusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - - name: global.clusterVersion - value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - - name: global.localClusterName - value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - - name: global.clusterPlatform - value: aws - - name: clusterGroup.name - value: factory - - name: clusterGroup.isHubCluster - value: "false" - destination: - server: https://kubernetes.default.svc - namespace: mypattern-factory - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: 20 - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.11 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" diff --git a/tests/common-acm-medical-diagnosis-hub.expected.yaml b/tests/common-acm-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index 959fbe30..00000000 --- a/tests/common-acm-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,309 +0,0 @@ ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-hub-ca-policy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-hub-ca-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-hub-ca-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: region-one-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: region-one-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: region-one-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-hub-ca-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: region-one-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: { - "matchLabels": { - "clusterGroup": "region-one" - } -} ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-hub-ca-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-hub-ca-config-policy - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: hub-ca - namespace: imperative - data: - hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' - hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: region-one-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: region-one-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: mypattern-region-one - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-region-one.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-region-one.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - - name: global.clusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - - name: global.clusterVersion - value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - - name: global.localClusterName - value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - - name: global.clusterPlatform - value: aws - - name: clusterGroup.name - value: region-one - - name: clusterGroup.isHubCluster - value: "false" - destination: - server: https://kubernetes.default.svc - namespace: mypattern-region-one - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: 20 - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.11 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" diff --git a/tests/common-acm-naked.expected.yaml b/tests/common-acm-naked.expected.yaml deleted file mode 100644 index 880ef747..00000000 --- a/tests/common-acm-naked.expected.yaml +++ /dev/null @@ -1,112 +0,0 @@ ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.11 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" diff --git a/tests/common-acm-normal.expected.yaml b/tests/common-acm-normal.expected.yaml deleted file mode 100644 index 87071cc4..00000000 --- a/tests/common-acm-normal.expected.yaml +++ /dev/null @@ -1,808 +0,0 @@ ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: v1 -kind: Secret -metadata: - name: aws-ap-acm-provision-edge-install-config -data: - # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWFwJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAxCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDAKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTIKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz -type: Opaque ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: v1 -kind: Secret -metadata: - name: azure-us-acm-provision-edge-install-config -data: - # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== -type: Opaque ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -# This pushes out the HUB's Certificate Authorities on to the imported clusters ---- -# Source: acm/templates/policies/private-repo-policies.yaml -# We copy the vp-private-repo-credentials from the "openshift-gitops" namespace -# to the "open-cluster-management" via the "private-hub-policy" -# -# Then we copy the secret from the "open-cluster-management" namespace to the -# managed clusters "openshift-gitops" instance -# -# And we also copy the same secret to the namespaced argo's namespace ---- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterClaim -metadata: - name: 'two-acm-provision-edge' - annotations: - argocd.argoproj.io/sync-wave: "20" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - cluster.open-cluster-management.io/createmanagedcluster: "true" - labels: - clusterClaimName: two-acm-provision-edge - clusterGroup: region -spec: - clusterPoolName: azure-us-acm-provision-edge ---- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterClaim -metadata: - name: 'three-acm-provision-edge' - annotations: - argocd.argoproj.io/sync-wave: "20" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - cluster.open-cluster-management.io/createmanagedcluster: "true" - labels: - clusterClaimName: three-acm-provision-edge - clusterGroup: region -spec: - clusterPoolName: azure-us-acm-provision-edge ---- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterPool -metadata: - name: "aws-ap-acm-provision-edge" - annotations: - argocd.argoproj.io/sync-wave: "10" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - labels: - cloud: aws - region: 'ap-southeast-2' - vendor: OpenShift - cluster.open-cluster-management.io/clusterset: aws-ap -spec: - size: 3 - runningCount: 0 - baseDomain: blueprints.rhecoeng.com - installConfigSecretTemplateRef: - name: aws-ap-acm-provision-edge-install-config - imageSetRef: - name: img4.10.18-multi-appsub - pullSecretRef: - name: aws-ap-acm-provision-edge-pull-secret - skipMachinePools: true # Disable MachinePool as using custom install-config - platform: - aws: - credentialsSecretRef: - name: aws-ap-acm-provision-edge-creds - region: ap-southeast-2 ---- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: hive.openshift.io/v1 -kind: ClusterPool -metadata: - name: "azure-us-acm-provision-edge" - annotations: - argocd.argoproj.io/sync-wave: "10" - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - labels: - cloud: azure - region: 'eastus' - vendor: OpenShift - cluster.open-cluster-management.io/clusterset: azure-us -spec: - size: 2 - runningCount: 2 - baseDomain: blueprints.rhecoeng.com - installConfigSecretTemplateRef: - name: azure-us-acm-provision-edge-install-config - imageSetRef: - name: img4.10.18-multi-appsub - pullSecretRef: - name: azure-us-acm-provision-edge-pull-secret - skipMachinePools: true # Disable MachinePool as using custom install-config - platform: - azure: - credentialsSecretRef: - name: azure-us-acm-provision-edge-creds - region: eastus ---- -# Source: acm/templates/provision/secrets-aws.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-ap-acm-provision-edge-creds -spec: - dataFrom: - - extract: - # Expects entries called: aws_access_key_id and aws_secret_access_key - key: secret/data/hub/aws - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-ap-acm-provision-edge-creds - creationPolicy: Owner - template: - type: Opaque ---- -# Source: acm/templates/provision/secrets-aws.yaml -# For use when manually creating clusters with ACM -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-ap-acm-provision-edge-infra-creds -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - - secretKey: awsKeyId - remoteRef: - key: secret/data/hub/aws - property: aws_access_key_id - - secretKey: awsAccessKey - remoteRef: - key: secret/data/hub/aws - property: aws_secret_access_key - - secretKey: sshPublicKey - remoteRef: - key: secret/data/hub/publickey - property: content - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-ap-acm-provision-edge-infra-creds - creationPolicy: Owner - template: - type: Opaque - metadata: - labels: - cluster.open-cluster-management.io/credentials: "" - cluster.open-cluster-management.io/type: aws - data: - baseDomain: "blueprints.rhecoeng.com" - pullSecret: |- - {{ .openshiftPullSecret | toString }} - aws_access_key_id: |- - {{ .awsKeyId | toString }} - aws_secret_access_key: |- - {{ .awsAccessKey | toString }} - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} - ssh-publickey: |- - {{ .sshPublicKey | toString }} - httpProxy: "" - httpsProxy: "" - noProxy: "" - additionalTrustBundle: "" ---- -# Source: acm/templates/provision/secrets-azure.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: azure-us-acm-provision-edge-creds -spec: - data: - - secretKey: azureOsServicePrincipal - remoteRef: - key: secret/data/hub/azureOsServicePrincipal - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: azure-us-acm-provision-edge-creds - creationPolicy: Owner - template: - type: Opaque - data: - osServicePrincipal.json: |- - {{ .azureOsServicePrincipal | toString }} ---- -# Source: acm/templates/provision/secrets-azure.yaml -# For use when manually creating clusters with ACM -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: azure-us-acm-provision-edge-infra-creds -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - - secretKey: sshPublicKey - remoteRef: - key: secret/data/hub/publickey - property: content - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - - secretKey: azureOsServicePrincipal - remoteRef: - key: secret/data/hub/azureOsServicePrincipal - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: azure-us-acm-provision-edge-infra-creds - creationPolicy: Owner - template: - type: Opaque - metadata: - labels: - cluster.open-cluster-management.io/credentials: "" - cluster.open-cluster-management.io/type: aws - data: - cloudName: AzurePublicCloud - osServicePrincipal.json: |- - {{ .azureOsServicePrincipal | toString }} - baseDomain: "blueprints.rhecoeng.com" - baseDomainResourceGroupName: "dojo-dns-zones" - pullSecret: |- - {{ .openshiftPullSecret | toString }} - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} - ssh-publickey: |- - {{ .sshPublicKey | toString }} - httpProxy: "" - httpsProxy: "" - noProxy: "" - additionalTrustBundle: "" ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-ap-acm-provision-edge-pull-secret -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-ap-acm-provision-edge-pull-secret - creationPolicy: Owner - template: - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: |- - {{ .openshiftPullSecret | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: aws-ap-acm-provision-edge-ssh-private-key -spec: - data: - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: aws-ap-acm-provision-edge-ssh-private-key - creationPolicy: Owner - template: - type: Opaque - data: - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: azure-us-acm-provision-edge-pull-secret -spec: - data: - - secretKey: openshiftPullSecret - remoteRef: - key: secret/data/hub/openshiftPullSecret - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: azure-us-acm-provision-edge-pull-secret - creationPolicy: Owner - template: - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: |- - {{ .openshiftPullSecret | toString }} ---- -# Source: acm/templates/provision/secrets-common.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: azure-us-acm-provision-edge-ssh-private-key -spec: - data: - - secretKey: sshPrivateKey - remoteRef: - key: secret/data/hub/privatekey - property: content - refreshInterval: 24h0m0s - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - target: - name: azure-us-acm-provision-edge-ssh-private-key - creationPolicy: Owner - template: - type: Opaque - data: - ssh-privatekey: |- - {{ .sshPrivateKey | toString }} ---- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: cluster.open-cluster-management.io/v1beta1 -kind: ManagedClusterSet -metadata: - annotations: - cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-edge-broker - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - name: acm-provision-edge -spec: - clusterSelector: - selectorType: LegacyClusterSetLabel ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-hub-ca-policy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-hub-ca-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-hub-ca-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-edge-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-edge-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-edge-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: acm-provision-edge-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-provision-edge-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-provision-edge-clustergroup-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: openshift-gitops-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: openshift-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: openshift-gitops-policy - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-hub-ca-policy-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-edge-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchLabels: - clusterGroup: acm-region ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: acm-provision-edge-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchLabels: - clusterGroup: region ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: openshift-gitops-placement - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' ---- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-hub-ca-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-hub-ca-config-policy - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: Secret - apiVersion: v1 - type: Opaque - metadata: - name: hub-ca - namespace: imperative - data: - hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' - hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' ---- -# Source: acm/templates/policies/application-policies.yaml -# TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-edge-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-edge-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: mypattern-acm-edge - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-acm-edge.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-edge.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - - name: global.clusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - - name: global.clusterVersion - value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - - name: global.localClusterName - value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - - name: global.clusterPlatform - value: aws - - name: clusterGroup.name - value: acm-edge - - name: clusterGroup.isHubCluster - value: "false" - destination: - server: https://kubernetes.default.svc - namespace: mypattern-acm-edge - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: 20 - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: acm-provision-edge-clustergroup-policy - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: acm-provision-edge-clustergroup-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - name: mypattern-acm-provision-edge - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground - spec: - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-acm-provision-edge.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-edge.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - - name: global.clusterDomain - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - - name: global.clusterVersion - value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - - name: global.localClusterName - value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - - name: global.clusterPlatform - value: aws - - name: clusterGroup.name - value: acm-provision-edge - - name: clusterGroup.isHubCluster - value: "false" - destination: - server: https://kubernetes.default.svc - namespace: mypattern-acm-provision-edge - syncPolicy: - automated: - prune: false - selfHeal: true - retry: - limit: 20 - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: openshift-gitops-policy - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.DS Data Security - policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: openshift-gitops-config - spec: - remediationAction: enforce - severity: medium - namespaceSelector: - include: - - default - object-templates: - - complianceType: mustonlyhave - objectDefinition: - # This is an auto-generated file. DO NOT EDIT - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: '' - spec: - channel: gitops-1.11 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: "*" diff --git a/tests/common-clustergroup-industrial-edge-factory.expected.yaml b/tests/common-clustergroup-industrial-edge-factory.expected.yaml deleted file mode 100644 index 7fde2b37..00000000 --- a/tests/common-clustergroup-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,773 +0,0 @@ ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-factory - name: manuela-stormshift-line-dashboard -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-factory - name: manuela-stormshift-machine-sensor -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-factory - name: manuela-stormshift-messaging -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-factory - name: manuela-factory-ml-workspace -spec: ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: mypattern-factory - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: mypattern-factory - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: mypattern-factory -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-factory - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: - - name: stormshift - path: charts/factory/manuela-stormshift - plugin: - name: helm-with-kustomize - project: factory - - name: odh - namespace: manuela-factory-ml-workspace - path: charts/datacenter/opendatahub - project: factory - argoCD: - configManagementPlugins: - - image: quay.io/hybridcloudpatterns/utility-container:latest - name: helm-with-kustomize - pluginArgs: - - --loglevel=debug - pluginConfig: | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-factory.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern=mypattern - --set global.clusterDomain=region.example.com - --set global.hubClusterDomain=apps.hub.example.com - --set global.localClusterDomain=apps.region.example.com - --set clusterGroup.name=factory - --post-renderer ./kustomize"] - initContainers: [] - imperative: - activeDeadlineSeconds: 3600 - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: - - name: test - playbook: ansible/test.yml - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: false - managedClusterGroups: {} - name: factory - namespaces: - - manuela-stormshift-line-dashboard - - manuela-stormshift-machine-sensor - - manuela-stormshift-messaging - - manuela-factory-ml-workspace - operatorgroupExcludes: - - manuela-factory-ml-workspace - projects: - - factory - sharedValueFiles: [] - subscriptions: - - channel: stable - name: opendatahub-operator - source: community-operators - - channel: stable - name: seldon-operator - namespace: manuela-stormshift-messaging - source: community-operators - - channel: stable - name: amq-streams - namespace: manuela-stormshift-messaging - - channel: 7.x - name: amq-broker-rhel8 - namespace: manuela-stormshift-messaging - - channel: stable - name: red-hat-camel-k - namespace: manuela-stormshift-messaging - targetCluster: in-cluster - enabled: all - global: - clusterDomain: region.example.com - clusterPlatform: aws - clusterVersion: "4.12" - extraValueFiles: [] - hubClusterDomain: apps.hub.example.com - localClusterDomain: apps.region.example.com - namespace: pattern-namespace - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Automatic - useCSV: false - pattern: mypattern - repoURL: https://github.com/pattern-clone/mypattern - secretStore: - backend: vault - targetRevision: main - main: - clusterGroupName: hub - git: - repoURL: https://github.com/pattern-clone/mypattern - revision: main - multiSourceConfig: - enabled: true - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml -kind: ConfigMap -apiVersion: v1 -metadata: - name: "argocd-cmp-helm-with-kustomize" - namespace: mypattern-factory -data: - "plugin.yaml": | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-factory.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern=mypattern - --set global.clusterDomain=region.example.com - --set global.hubClusterDomain=apps.hub.example.com - --set global.localClusterDomain=apps.region.example.com - --set clusterGroup.name=factory - --post-renderer ./kustomize"] ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: mypattern-factory-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: factory-gitops-argocd-application-controller - namespace: mypattern-factory - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: factory-gitops-argocd-server - namespace: mypattern-factory - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: factory-gitops-argocd-dex-server - namespace: mypattern-factory ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-admin-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/job.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: imperative-cronjob - namespace: imperative -spec: - schedule: "*/10 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: imperative-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; - fi; - fi; - mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - - name: test - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - ansible/test.yml - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-factory - restartPolicy: Never ---- -# Source: clustergroup/templates/core/subscriptions.yaml ---- ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: factory - namespace: mypattern-factory -spec: - description: "Pattern factory" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: stormshift - namespace: mypattern-factory - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: mypattern-factory - project: factory - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/factory/manuela-stormshift - plugin: { - "name": "helm-with-kustomize" -} - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: odh - namespace: mypattern-factory - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-factory-ml-workspace - project: factory - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/opendatahub - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-factory.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-factory.yaml" - - "/values-4.12-factory.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: factory-gitops - namespace: mypattern-factory - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - sidecarContainers: - - name: helm-with-kustomize - command: [/var/run/argocd/argocd-cmp-server] - args: [ - "--loglevel=debug" -] - image: quay.io/hybridcloudpatterns/utility-container:latest - imagePullPolicy: Always - securityContext: - runAsNonRoot: true - volumeMounts: - - mountPath: /var/run/argocd - name: var-files - - mountPath: /home/argocd/cmp-server/plugins - name: plugins - - mountPath: /tmp - name: cmp-tmp - - mountPath: /home/argocd/cmp-server/config/plugin.yaml - subPath: plugin.yaml - name: helm-with-kustomize - volumes: - - emptyDir: {} - name: cmp-tmp - - configMap: - name: "argocd-cmp-helm-with-kustomize" - name: helm-with-kustomize - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: factory-gitops-link - namespace: mypattern-factory -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://factory-gitops-server-mypattern-factory.apps.region.example.com' - location: ApplicationMenu - text: 'Factory ArgoCD' ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-stormshift-line-dashboard-operator-group - namespace: manuela-stormshift-line-dashboard -spec: - targetNamespaces: - - manuela-stormshift-line-dashboard ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-stormshift-machine-sensor-operator-group - namespace: manuela-stormshift-machine-sensor -spec: - targetNamespaces: - - manuela-stormshift-machine-sensor ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-stormshift-messaging-operator-group - namespace: manuela-stormshift-messaging -spec: - targetNamespaces: - - manuela-stormshift-messaging ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: opendatahub-operator - namespace: openshift-operators -spec: - name: opendatahub-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: seldon-operator - namespace: manuela-stormshift-messaging -spec: - name: seldon-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-streams - namespace: manuela-stormshift-messaging -spec: - name: amq-streams - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-broker-rhel8 - namespace: manuela-stormshift-messaging -spec: - name: amq-broker-rhel8 - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: 7.x - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: red-hat-camel-k - namespace: manuela-stormshift-messaging -spec: - name: red-hat-camel-k - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic diff --git a/tests/common-clustergroup-industrial-edge-hub.expected.yaml b/tests/common-clustergroup-industrial-edge-hub.expected.yaml deleted file mode 100644 index 0c0d231d..00000000 --- a/tests/common-clustergroup-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,1590 +0,0 @@ ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: golang-external-secrets -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: external-secrets -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: open-cluster-management -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: manuela-ml-workspace -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: manuela-tst-all -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: manuela-ci -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: manuela-data-lake -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: staging -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-datacenter - name: vault -spec: ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: mypattern-datacenter - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: mypattern-datacenter - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: mypattern-datacenter -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-datacenter - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: - acm: - ignoreDifferences: - - group: internal.open-cluster-management.io - jsonPointers: - - /spec/loggingCA - kind: ManagedClusterInfo - name: acm - namespace: open-cluster-management - path: common/acm - project: datacenter - odh: - name: odh - namespace: manuela-ml-workspace - path: charts/datacenter/opendatahub - project: datacenter - pipelines: - name: pipelines - namespace: manuela-ci - path: charts/datacenter/pipelines - project: datacenter - production-data-lake: - ignoreDifferences: - - group: apps - jsonPointers: - - /spec/replicas - kind: Deployment - - group: route.openshift.io - jsonPointers: - - /status - kind: Route - - group: image.openshift.io - jsonPointers: - - /spec/tags - kind: ImageStream - - group: apps.openshift.io - jsonPointers: - - /spec/template/spec/containers/0/image - kind: DeploymentConfig - name: production-data-lake - namespace: manuela-data-lake - path: charts/datacenter/manuela-data-lake - project: production-datalake - secrets: - name: external-secrets - namespace: external-secrets - path: charts/datacenter/external-secrets - project: golang-external-secrets - secrets-operator: - name: golang-external-secrets - namespace: golang-external-secrets - path: common/golang-external-secrets - project: golang-external-secrets - test: - name: manuela-test - namespace: manuela-tst-all - path: charts/datacenter/manuela-tst - plugin: - name: helm-with-kustomize - project: datacenter - vault: - chart: vault - name: vault - namespace: vault - overrides: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: LoadBalancer - - name: server.route.enabled - value: "true" - - name: server.route.host - value: null - - name: server.route.tls.termination - value: edge - - name: server.image.repository - value: registry.connect.redhat.com/hashicorp/vault - - name: server.image.tag - value: 1.10.3-ubi - project: datacenter - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - argoCD: - configManagementPlugins: - - image: quay.io/hybridcloudpatterns/utility-container:latest - name: helm-with-kustomize - pluginArgs: - - --loglevel=debug - pluginConfig: | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-datacenter.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern=mypattern - --set global.clusterDomain=region.example.com - --set global.hubClusterDomain=apps.hub.example.com - --set global.localClusterDomain=apps.region.example.com - --set clusterGroup.name=datacenter - --post-renderer ./kustomize"] - initContainers: [] - imperative: - activeDeadlineSeconds: 3600 - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: - - name: test - playbook: ansible/test.yml - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: true - managedClusterGroups: - factory: - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - matchLabels: - clusterGroup: factory - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" - name: factory - name: datacenter - namespaces: - - golang-external-secrets - - external-secrets - - open-cluster-management - - manuela-ml-workspace - - manuela-tst-all - - manuela-ci - - manuela-data-lake - - staging - - vault - operatorgroupExcludes: - - manuela-ml-workspace - projects: - - datacenter - - production-datalake - - golang-external-secrets - - vault - sharedValueFiles: [] - subscriptions: - acm: - channel: release-2.6 - name: advanced-cluster-management - namespace: open-cluster-management - amqbroker-prod: - channel: 7.x - name: amq-broker-rhel8 - namespace: manuela-tst-all - amqstreams-prod-dev: - channel: stable - name: amq-streams - namespaces: - - manuela-data-lake - - manuela-tst-all - camelk-prod-dev: - channel: stable - name: red-hat-camel-k - namespaces: - - manuela-data-lake - - manuela-tst-all - odh: - channel: stable - name: opendatahub-operator - source: community-operators - pipelines: - channel: latest - name: openshift-pipelines-operator-rh - source: redhat-operators - seldon-prod-dev: - channel: stable - name: seldon-operator - namespaces: - - manuela-ml-workspace - - manuela-tst-all - source: community-operators - targetCluster: in-cluster - enabled: all - global: - clusterDomain: region.example.com - clusterPlatform: aws - clusterVersion: "4.12" - extraValueFiles: [] - hubClusterDomain: apps.hub.example.com - localClusterDomain: apps.region.example.com - namespace: pattern-namespace - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Automatic - useCSV: false - pattern: mypattern - repoURL: https://github.com/pattern-clone/mypattern - secretStore: - backend: vault - targetRevision: main - main: - clusterGroupName: hub - git: - repoURL: https://github.com/pattern-clone/mypattern - revision: main - multiSourceConfig: - enabled: true - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/plumbing/argocd-cmp-plugin-cms.yaml -kind: ConfigMap -apiVersion: v1 -metadata: - name: "argocd-cmp-helm-with-kustomize" - namespace: mypattern-datacenter -data: - "plugin.yaml": | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: helm-with-kustomize - spec: - preserveFileMode: true - init: - command: ["/bin/sh", "-c"] - args: ["helm dependency build"] - generate: - command: ["/bin/bash", "-c"] - args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} - -f $(git rev-parse --show-toplevel)/values-global.yaml - -f $(git rev-parse --show-toplevel)/values-datacenter.yaml - --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL - --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION - --set global.namespace=$ARGOCD_APP_NAMESPACE - --set global.pattern=mypattern - --set global.clusterDomain=region.example.com - --set global.hubClusterDomain=apps.hub.example.com - --set global.localClusterDomain=apps.region.example.com - --set clusterGroup.name=datacenter - --post-renderer ./kustomize"] ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: mypattern-datacenter-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: datacenter-gitops-argocd-application-controller - namespace: mypattern-datacenter - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: datacenter-gitops-argocd-server - namespace: mypattern-datacenter - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: datacenter-gitops-argocd-dex-server - namespace: mypattern-datacenter ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-admin-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/job.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: imperative-cronjob - namespace: imperative -spec: - schedule: "*/10 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: imperative-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; - fi; - fi; - mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - - name: test - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - ansible/test.yml - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-datacenter - restartPolicy: Never ---- -# Source: clustergroup/templates/imperative/unsealjob.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: imperative -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; - fi; - fi; - mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - - name: unseal-playbook - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-datacenter - restartPolicy: Never ---- -# Source: clustergroup/templates/core/subscriptions.yaml ---- ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: datacenter - namespace: mypattern-datacenter -spec: - description: "Pattern datacenter" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: production-datalake - namespace: mypattern-datacenter -spec: - description: "Pattern production-datalake" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: golang-external-secrets - namespace: mypattern-datacenter -spec: - description: "Pattern golang-external-secrets" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: vault - namespace: mypattern-datacenter -spec: - description: "Pattern vault" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: acm - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: open-cluster-management - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/acm - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - ignoreDifferences: [ - { - "group": "internal.open-cluster-management.io", - "jsonPointers": [ - "/spec/loggingCA" - ], - "kind": "ManagedClusterInfo" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: odh - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-ml-workspace - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/opendatahub - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: pipelines - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-ci - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/pipelines - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: production-data-lake - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-data-lake - project: production-datalake - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/manuela-data-lake - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - ignoreDifferences: [ - { - "group": "apps", - "jsonPointers": [ - "/spec/replicas" - ], - "kind": "Deployment" - }, - { - "group": "route.openshift.io", - "jsonPointers": [ - "/status" - ], - "kind": "Route" - }, - { - "group": "image.openshift.io", - "jsonPointers": [ - "/spec/tags" - ], - "kind": "ImageStream" - }, - { - "group": "apps.openshift.io", - "jsonPointers": [ - "/spec/template/spec/containers/0/image" - ], - "kind": "DeploymentConfig" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: external-secrets - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: external-secrets - project: golang-external-secrets - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/external-secrets - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: golang-external-secrets - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: golang-external-secrets - project: golang-external-secrets - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/golang-external-secrets - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: manuela-test - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: manuela-tst-all - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/manuela-tst - plugin: { - "name": "helm-with-kustomize" -} - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: vault - namespace: mypattern-datacenter - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: vault - project: datacenter - source: - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - chart: vault - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-datacenter.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-datacenter.yaml" - - "/values-4.12-datacenter.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: "LoadBalancer" - - name: server.route.enabled - value: "true" - - name: server.route.host - value: - - name: server.route.tls.termination - value: "edge" - - name: server.image.repository - value: "registry.connect.redhat.com/hashicorp/vault" - - name: server.image.tag - value: "1.10.3-ubi" - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: datacenter-gitops - namespace: mypattern-datacenter - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - sidecarContainers: - - name: helm-with-kustomize - command: [/var/run/argocd/argocd-cmp-server] - args: [ - "--loglevel=debug" -] - image: quay.io/hybridcloudpatterns/utility-container:latest - imagePullPolicy: Always - securityContext: - runAsNonRoot: true - volumeMounts: - - mountPath: /var/run/argocd - name: var-files - - mountPath: /home/argocd/cmp-server/plugins - name: plugins - - mountPath: /tmp - name: cmp-tmp - - mountPath: /home/argocd/cmp-server/config/plugin.yaml - subPath: plugin.yaml - name: helm-with-kustomize - volumes: - - emptyDir: {} - name: cmp-tmp - - configMap: - name: "argocd-cmp-helm-with-kustomize" - name: helm-with-kustomize - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: datacenter-gitops-link - namespace: mypattern-datacenter -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://datacenter-gitops-server-mypattern-datacenter.apps.region.example.com' - location: ApplicationMenu - text: 'Datacenter ArgoCD' ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: golang-external-secrets-operator-group - namespace: golang-external-secrets -spec: - targetNamespaces: - - golang-external-secrets ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: external-secrets-operator-group - namespace: external-secrets -spec: - targetNamespaces: - - external-secrets ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: open-cluster-management-operator-group - namespace: open-cluster-management -spec: - targetNamespaces: - - open-cluster-management ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-tst-all-operator-group - namespace: manuela-tst-all -spec: - targetNamespaces: - - manuela-tst-all ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-ci-operator-group - namespace: manuela-ci -spec: - targetNamespaces: - - manuela-ci ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: manuela-data-lake-operator-group - namespace: manuela-data-lake -spec: - targetNamespaces: - - manuela-data-lake ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: staging-operator-group - namespace: staging -spec: - targetNamespaces: - - staging ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: vault-operator-group - namespace: vault -spec: - targetNamespaces: - - vault ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: advanced-cluster-management - namespace: open-cluster-management -spec: - name: advanced-cluster-management - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: release-2.6 - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-broker-rhel8 - namespace: manuela-tst-all -spec: - name: amq-broker-rhel8 - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: 7.x - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-streams - namespace: manuela-data-lake -spec: - name: amq-streams - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-streams - namespace: manuela-tst-all -spec: - name: amq-streams - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: red-hat-camel-k - namespace: manuela-data-lake -spec: - name: red-hat-camel-k - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: red-hat-camel-k - namespace: manuela-tst-all -spec: - name: red-hat-camel-k - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: opendatahub-operator - namespace: openshift-operators -spec: - name: opendatahub-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-pipelines-operator-rh - namespace: openshift-operators -spec: - name: openshift-pipelines-operator-rh - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: latest - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: seldon-operator - namespace: manuela-ml-workspace -spec: - name: seldon-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: seldon-operator - namespace: manuela-tst-all -spec: - name: seldon-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic diff --git a/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml b/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index 26d722c4..00000000 --- a/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,1669 +0,0 @@ ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: open-cluster-management -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: openshift-serverless -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: opendatahub -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: openshift-storage -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: xraylab-1 -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: knative-serving -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: staging -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: vault -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-hub - name: golang-external-secrets -spec: ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: mypattern-hub - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: mypattern-hub - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: mypattern-hub -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-hub - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: - golang-external-secrets: - name: golang-external-secrets - namespace: golang-external-secrets - path: common/golang-external-secrets - project: hub - kafdrop: - name: kafdrop - namespace: xraylab-1 - path: charts/all/kafdrop - project: medical-diagnosis - kafka: - name: kafka - namespace: xraylab-1 - path: charts/all/kafka - project: medical-diagnosis - opendatahub: - name: odh - namespace: opendatahub - path: charts/all/opendatahub - project: medical-diagnosis - openshift-data-foundations: - name: odf - namespace: openshift-storage - path: charts/all/openshift-data-foundations - project: medical-diagnosis - openshift-serverless: - name: serverless - namespace: xraylab-1 - path: charts/all/openshift-serverless - project: medical-diagnosis - service-account: - name: xraylab-service-account - namespace: xraylab-1 - path: charts/all/medical-diagnosis/service-account - project: medical-diagnosis - vault: - chart: vault - name: vault - namespace: vault - overrides: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: LoadBalancer - - name: server.route.enabled - value: "true" - - name: server.route.host - value: null - - name: server.route.tls.termination - value: edge - - name: server.image.repository - value: registry.connect.redhat.com/hashicorp/vault - - name: server.image.tag - value: 1.10.3-ubi - project: hub - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - xraylab-database: - name: xraylab-database - namespace: xraylab-1 - path: charts/all/medical-diagnosis/database - project: medical-diagnosis - xraylab-grafana-dashboards: - name: xraylab-grafana-dashboards - namespace: xraylab-1 - path: charts/all/medical-diagnosis/grafana - project: medical-diagnosis - xraylab-image-generator: - ignoreDifferences: - - group: apps.openshift.io - jqPathExpressions: - - .spec.template.spec.containers[].image - kind: DeploymentConfig - name: xraylab-image-generator - namespace: xraylab-1 - path: charts/all/medical-diagnosis/image-generator - project: medical-diagnosis - xraylab-image-server: - ignoreDifferences: - - group: apps.openshift.io - jqPathExpressions: - - .spec.template.spec.containers[].image - kind: DeploymentConfig - name: xraylab-image-server - namespace: xraylab-1 - path: charts/all/medical-diagnosis/image-server - project: medical-diagnosis - xraylab-init: - name: xraylab-init - namespace: xraylab-1 - path: charts/all/medical-diagnosis/xray-init - project: medical-diagnosis - argoCD: - configManagementPlugins: [] - initContainers: [] - imperative: - activeDeadlineSeconds: 3600 - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: - - name: test - playbook: ansible/test.yml - timeout: 234 - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: true - managedClusterGroups: - region-one: - clusterSelector: - matchLabels: - clusterGroup: region-one - helmOverrides: - - name: clusterGroup.isHubCluster - value: false - name: region-one - name: hub - namespaces: - - open-cluster-management - - openshift-serverless - - opendatahub - - openshift-storage - - xraylab-1 - - knative-serving - - staging - - vault - - golang-external-secrets - projects: - - hub - - medical-diagnosis - sharedValueFiles: [] - subscriptions: - amq-streams: - channel: stable - name: amq-streams - namespace: xraylab-1 - grafana: - channel: v4 - name: grafana-operator - namespace: xraylab-1 - source: community-operators - odf: - channel: stable-4.11 - name: odf-operator - namespace: openshift-storage - opendatahub: - name: opendatahub-operator - source: community-operators - severless: - channel: stable - name: serverless-operator - targetCluster: in-cluster - enabled: all - global: - clusterDomain: region.example.com - clusterPlatform: aws - clusterVersion: "4.12" - extraValueFiles: [] - hubClusterDomain: apps.hub.example.com - localClusterDomain: apps.region.example.com - namespace: pattern-namespace - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Automatic - useCSV: false - pattern: mypattern - repoURL: https://github.com/pattern-clone/mypattern - secretStore: - backend: vault - targetRevision: main - main: - clusterGroupName: hub - git: - repoURL: https://github.com/pattern-clone/mypattern - revision: main - multiSourceConfig: - enabled: true - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: mypattern-hub-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: hub-gitops-argocd-application-controller - namespace: mypattern-hub - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: hub-gitops-argocd-server - namespace: mypattern-hub - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: hub-gitops-argocd-dex-server - namespace: mypattern-hub ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-admin-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/job.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: imperative-cronjob - namespace: imperative -spec: - schedule: "*/10 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: imperative-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; - fi; - fi; - mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - - name: test - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "234" - - ansible-playbook - - -e - - "@/values/values.yaml" - - ansible/test.yml - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-hub - restartPolicy: Never ---- -# Source: clustergroup/templates/imperative/unsealjob.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: imperative -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; - fi; - fi; - mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - - name: unseal-playbook - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-hub - restartPolicy: Never ---- -# Source: clustergroup/templates/core/subscriptions.yaml ---- ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: hub - namespace: mypattern-hub -spec: - description: "Pattern hub" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: medical-diagnosis - namespace: mypattern-hub -spec: - description: "Pattern medical-diagnosis" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: golang-external-secrets - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: golang-external-secrets - project: hub - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/golang-external-secrets - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: kafdrop - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/kafdrop - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: kafka - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/kafka - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: odh - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: opendatahub - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/opendatahub - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: odf - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: openshift-storage - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/openshift-data-foundations - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: serverless - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/openshift-serverless - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-service-account - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/service-account - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: vault - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: vault - project: hub - source: - repoURL: https://helm.releases.hashicorp.com - targetRevision: v0.20.1 - chart: vault - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - - name: global.openshift - value: "true" - - name: injector.enabled - value: "false" - - name: ui.enabled - value: "true" - - name: ui.serviceType - value: "LoadBalancer" - - name: server.route.enabled - value: "true" - - name: server.route.host - value: - - name: server.route.tls.termination - value: "edge" - - name: server.image.repository - value: "registry.connect.redhat.com/hashicorp/vault" - - name: server.image.tag - value: "1.10.3-ubi" - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-database - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/database - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-grafana-dashboards - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/grafana - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-image-generator - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/image-generator - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - ignoreDifferences: [ - { - "group": "apps.openshift.io", - "jqPathExpressions": [ - ".spec.template.spec.containers[].image" - ], - "kind": "DeploymentConfig" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-image-server - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/image-server - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - ignoreDifferences: [ - { - "group": "apps.openshift.io", - "jqPathExpressions": [ - ".spec.template.spec.containers[].image" - ], - "kind": "DeploymentConfig" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: xraylab-init - namespace: mypattern-hub - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: xraylab-1 - project: medical-diagnosis - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/all/medical-diagnosis/xray-init - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-hub.yaml" - - "/values-4.12-hub.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: hub-gitops - namespace: mypattern-hub - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: hub-gitops-link - namespace: mypattern-hub -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://hub-gitops-server-mypattern-hub.apps.region.example.com' - location: ApplicationMenu - text: 'Hub ArgoCD' ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: open-cluster-management-operator-group - namespace: open-cluster-management -spec: - targetNamespaces: - - open-cluster-management ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: openshift-serverless-operator-group - namespace: openshift-serverless -spec: - targetNamespaces: - - openshift-serverless ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: opendatahub-operator-group - namespace: opendatahub -spec: - targetNamespaces: - - opendatahub ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: openshift-storage-operator-group - namespace: openshift-storage -spec: - targetNamespaces: - - openshift-storage ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: xraylab-1-operator-group - namespace: xraylab-1 -spec: - targetNamespaces: - - xraylab-1 ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: knative-serving-operator-group - namespace: knative-serving -spec: - targetNamespaces: - - knative-serving ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: staging-operator-group - namespace: staging -spec: - targetNamespaces: - - staging ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: vault-operator-group - namespace: vault -spec: - targetNamespaces: - - vault ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: golang-external-secrets-operator-group - namespace: golang-external-secrets -spec: - targetNamespaces: - - golang-external-secrets ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: amq-streams - namespace: xraylab-1 -spec: - name: amq-streams - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: grafana-operator - namespace: xraylab-1 -spec: - name: grafana-operator - source: community-operators - sourceNamespace: openshift-marketplace - channel: v4 - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: odf-operator - namespace: openshift-storage -spec: - name: odf-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable-4.11 - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: opendatahub-operator - namespace: openshift-operators -spec: - name: opendatahub-operator - source: community-operators - sourceNamespace: openshift-marketplace - installPlanApproval: Automatic ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: serverless-operator - namespace: openshift-operators -spec: - name: serverless-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: stable - installPlanApproval: Automatic diff --git a/tests/common-clustergroup-naked.expected.yaml b/tests/common-clustergroup-naked.expected.yaml deleted file mode 100644 index 194bfa8f..00000000 --- a/tests/common-clustergroup-naked.expected.yaml +++ /dev/null @@ -1,405 +0,0 @@ ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: common-example - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: common-example - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: common-example -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-example - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: {} - argoCD: - configManagementPlugins: [] - initContainers: [] - imperative: - activeDeadlineSeconds: 3600 - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: [] - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: true - managedClusterGroups: {} - name: example - namespaces: [] - projects: [] - sharedValueFiles: [] - subscriptions: {} - targetCluster: in-cluster - enabled: all - global: - extraValueFiles: [] - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Automatic - useCSV: true - pattern: common - secretStore: - backend: vault - targetRevision: main - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-example-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: example-gitops-argocd-application-controller - namespace: common-example - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: example-gitops-argocd-server - namespace: common-example - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: example-gitops-argocd-dex-server - namespace: common-example ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-admin-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/unsealjob.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: imperative -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL=""; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; - fi; - fi; - mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - - name: unseal-playbook - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example - restartPolicy: Never ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: example-gitops - namespace: common-example - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: example-gitops-link - namespace: common-example -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://example-gitops-server-common-example.' - location: ApplicationMenu - text: 'Example ArgoCD' diff --git a/tests/common-clustergroup-normal.expected.yaml b/tests/common-clustergroup-normal.expected.yaml deleted file mode 100644 index af54bedc..00000000 --- a/tests/common-clustergroup-normal.expected.yaml +++ /dev/null @@ -1,1169 +0,0 @@ ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: open-cluster-management - labels: - argocd.argoproj.io/managed-by: mypattern-example - kubernetes.io/os: "linux" - openshift.io/node-selector: "" - annotations: - openshift.io/cluster-monitoring: "true" - owner: "namespace owner" -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: application-ci - labels: - argocd.argoproj.io/managed-by: mypattern-example -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: exclude-targetns - labels: - argocd.argoproj.io/managed-by: mypattern-example -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-example - name: include-ci -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - argocd.argoproj.io/managed-by: mypattern-example - name: exclude-og -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: totally-exclude-og - labels: - argocd.argoproj.io/managed-by: mypattern-example -spec: ---- -# Source: clustergroup/templates/core/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: include-default-og - labels: - argocd.argoproj.io/managed-by: mypattern-example -spec: ---- -# Source: clustergroup/templates/imperative/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: imperative - argocd.argoproj.io/managed-by: mypattern-example - name: imperative ---- -# Source: clustergroup/templates/plumbing/gitops-namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: mypattern-example - # The name here needs to be consistent with - # - acm/templates/policies/application-policies.yaml - # - clustergroup/templates/applications.yaml - # - any references to secrets and route URLs in documentation - name: mypattern-example -spec: {} ---- -# Source: clustergroup/templates/imperative/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: helm-values-configmap-example - namespace: imperative -data: - values.yaml: | - clusterGroup: - applications: - acm: - ignoreDifferences: - - group: internal.open-cluster-management.io - jsonPointers: - - /spec/loggingCA - kind: ManagedClusterInfo - name: acm - namespace: open-cluster-management - path: common/acm - project: datacenter - pipe: - extraValueFiles: - - /values/4.12/aws.yaml - name: pipelines - namespace: application-ci - path: charts/datacenter/pipelines - project: datacenter - argoCD: - configManagementPlugins: [] - initContainers: [] - imperative: - activeDeadlineSeconds: 3600 - clusterRoleName: imperative-cluster-role - clusterRoleYaml: "" - cronJobName: imperative-cronjob - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - insecureUnsealVaultInsideClusterSchedule: '*/5 * * * *' - jobName: imperative-job - jobs: - - name: test - playbook: ansible/test.yml - timeout: 234 - namespace: imperative - roleName: imperative-role - roleYaml: "" - schedule: '*/10 * * * *' - serviceAccountCreate: true - serviceAccountName: imperative-sa - valuesConfigMap: helm-values-configmap - verbosity: "" - isHubCluster: true - managedClusterGroups: - - acmlabels: - - name: clusterGroup - value: acm-region - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" - name: acm-edge - targetRevision: main - - acmlabels: - - name: clusterGroup - value: region - clusterPools: - exampleAWSPool: - baseDomain: blueprints.rhecoeng.com - controlPlane: - count: 1 - platform: - aws: - type: m5.xlarge - name: aws-ap - openshiftVersion: 4.10.18 - platform: - aws: - region: ap-southeast-2 - size: 3 - workers: - count: 0 - exampleAzurePool: - baseDomain: blueprints.rhecoeng.com - clusters: - - Two - - three - name: azure-us - openshiftVersion: 4.10.18 - platform: - azure: - baseDomainResourceGroupName: dojo-dns-zones - region: eastus - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" - name: acm-provision-edge - targetRevision: main - - helmOverrides: - - name: clusterGroup.isHubCluster - value: "false" - hostedArgoSites: - - domain: perth1.beekhof.net - name: perth - - domain: syd.beekhof.net - name: sydney - name: argo-edge - name: example - namespaces: - - open-cluster-management: - annotations: - openshift.io/cluster-monitoring: "true" - owner: namespace owner - labels: - kubernetes.io/os: linux - openshift.io/node-selector: "" - - application-ci: - operatorGroup: true - targetNamespaces: - - application-ci - - other-namespace - - exclude-targetns: - operatorGroup: true - targetNamespaces: null - - include-ci - - exclude-og - - totally-exclude-og: - operatorGroup: false - - include-default-og: - operatorGroup: true - operatorgroupExcludes: - - exclude-og - projects: - - datacenter - sharedValueFiles: - - /values/aws.yaml - - /values/4.12.yaml - subscriptions: - acm: - channel: release-2.4 - csv: advanced-cluster-management.v2.4.1 - name: advanced-cluster-management - namespace: open-cluster-management - odh: - csv: opendatahub-operator.v1.1.0 - disabled: true - name: opendatahub-operator - source: community-operators - pipelines: - csv: redhat-openshift-pipelines.v1.5.2 - name: openshift-pipelines-operator-rh - targetCluster: in-cluster - enabled: all - global: - clusterDomain: region.example.com - clusterPlatform: aws - clusterVersion: "4.12" - extraValueFiles: [] - hubClusterDomain: apps.hub.example.com - localClusterDomain: apps.region.example.com - multiClusterTarget: all - namespace: pattern-namespace - options: - applicationRetryLimit: 20 - installPlanApproval: Automatic - syncPolicy: Automatic - useCSV: false - pattern: mypattern - repoURL: https://github.com/pattern-clone/mypattern - secretStore: - backend: vault - targetRevision: main - main: - clusterGroupName: hub - git: - repoURL: https://github.com/pattern-clone/mypattern - revision: main - multiSourceConfig: - enabled: true - secretStore: - kind: ClusterSecretStore - name: vault-backend ---- -# Source: clustergroup/templates/imperative/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: imperative-cluster-role -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: imperative-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: imperative-cluster-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: openshift-gitops-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - name: openshift-gitops-argocd-server - namespace: openshift-gitops ---- -# Source: clustergroup/templates/plumbing/argocd-super-role.yaml -# WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: mypattern-example-cluster-admin-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-application-controller - name: example-gitops-argocd-application-controller - namespace: mypattern-example - # NOTE: THIS MUST BE FIXED FOR MULTITENANT SETUP - - kind: ServiceAccount - # This is the {ArgoCD.name}-argocd-server - name: example-gitops-argocd-server - namespace: mypattern-example - # NOTE: This is needed starting with gitops-1.5.0 (see issue common#76) - - kind: ServiceAccount - name: example-gitops-argocd-dex-server - namespace: mypattern-example ---- -# Source: clustergroup/templates/imperative/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: imperative-role - namespace: imperative -rules: - - apiGroups: - - '*' - resources: - - '*' - verbs: - - '*' ---- -# Source: clustergroup/templates/imperative/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: imperative-admin-rolebinding - namespace: imperative -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: imperative-role -subjects: - - kind: ServiceAccount - name: imperative-sa - namespace: imperative ---- -# Source: clustergroup/templates/imperative/job.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: imperative-cronjob - namespace: imperative -spec: - schedule: "*/10 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: imperative-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; - fi; - fi; - mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - - name: test - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "234" - - ansible-playbook - - -e - - "@/values/values.yaml" - - ansible/test.yml - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example - restartPolicy: Never ---- -# Source: clustergroup/templates/imperative/unsealjob.yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: unsealvault-cronjob - namespace: imperative -spec: - schedule: "*/5 * * * *" - # if previous Job is still running, skip execution of a new Job - concurrencyPolicy: Forbid - jobTemplate: - spec: - activeDeadlineSeconds: 3600 - template: - metadata: - name: unsealvault-job - spec: - serviceAccountName: imperative-sa - initContainers: - # git init happens in /git/repo so that we can set the folder to 0770 permissions - # reason for that is ansible refuses to create temporary folders in there - - name: git-init - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="https://github.com/pattern-clone/mypattern"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode}}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.username | base64decode }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.password | base64decode }}')"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - echo "USER/PASS: ${URL}"; - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{index .data.sshPrivateKey | base64decode }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo https://github.com/pattern-clone/mypattern | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - echo "SSH: ${URL}"; - fi; - fi; - mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; - volumeMounts: - - name: git - mountPath: "/git" - - name: unseal-playbook - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - env: - - name: HOME - value: /git/home - workingDir: /git/repo - # We have a default timeout of 600s for each playbook. Can be overridden - # on a per-job basis - command: - - timeout - - "600" - - ansible-playbook - - -e - - "@/values/values.yaml" - - -t - - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - - "common/ansible/playbooks/vault/vault.yaml" - volumeMounts: - - name: git - mountPath: "/git" - - name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml - containers: - - name: "done" - image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest - imagePullPolicy: Always - command: - - 'sh' - - '-c' - - 'echo' - - 'done' - - '\n' - volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: helm-values-configmap-example - restartPolicy: Never ---- -# Source: clustergroup/templates/core/subscriptions.yaml ---- ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: argo-edge - namespace: openshift-gitops -spec: - description: "Cluster Group argo-edge" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/projects.yaml -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: datacenter - namespace: mypattern-example -spec: - description: "Pattern datacenter" - destinations: - - namespace: '*' - server: '*' - clusterResourceWhitelist: - - group: '*' - kind: '*' - namespaceResourceWhitelist: - - group: '*' - kind: '*' - sourceRepos: - - '*' -status: {} ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: acm - namespace: mypattern-example - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: open-cluster-management - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/acm - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-example.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-example.yaml" - - "/values-4.12-example.yaml" - - "/values/aws.yaml" - - "/values/4.12.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - ignoreDifferences: [ - { - "group": "internal.open-cluster-management.io", - "jsonPointers": [ - "/spec/loggingCA" - ], - "kind": "ManagedClusterInfo" - } -] - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/applications.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: pipelines - namespace: mypattern-example - labels: - validatedpatterns.io/pattern: mypattern - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: application-ci - project: datacenter - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: charts/datacenter/pipelines - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-example.yaml" - - "/values-aws.yaml" - - "/values-aws-4.12.yaml" - - "/values-aws-example.yaml" - - "/values-4.12-example.yaml" - - "/values/aws.yaml" - - "/values/4.12.yaml" - - "/values/4.12/aws.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.clusterDomain - value: region.example.com - - name: global.clusterVersion - value: "4.12" - - name: global.clusterPlatform - value: "aws" - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.region.example.com - - name: global.privateRepo - value: - syncPolicy: - automated: {} - retry: - limit: 20 ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: mypattern-argo-edge-perth - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: argo-edge - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-argo-edge.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.perth1.beekhof.net - - name: global.clusterDomain - value: perth1.beekhof.net - - name: enabled - value: core - - name: clusterGroup.name - value: argo-edge - - name: clusterGroup.targetCluster - value: perth - - name: clusterGroup.hostedSite.secretsPath - value: secret/data/hub/cluster_perth - - name: clusterGroup.isHubCluster - value: "false" - destination: - name: perth - namespace: mypattern-argo-edge - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: mypattern-argo-edge-perth-plumbing - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: argo-edge - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-argo-edge.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.perth1.beekhof.net - - name: global.clusterDomain - value: perth1.beekhof.net - - name: enabled - value: plumbing - - name: clusterGroup.name - value: argo-edge - - name: clusterGroup.targetCluster - value: perth - - name: clusterGroup.hostedSite.secretsPath - value: secret/data/hub/cluster_perth - - name: clusterGroup.isHubCluster - value: "false" - destination: - name: in-cluster - namespace: openshift-gitops - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: mypattern-argo-edge-sydney - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: argo-edge - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-argo-edge.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.syd.beekhof.net - - name: global.clusterDomain - value: syd.beekhof.net - - name: enabled - value: core - - name: clusterGroup.name - value: argo-edge - - name: clusterGroup.targetCluster - value: sydney - - name: clusterGroup.hostedSite.secretsPath - value: secret/data/hub/cluster_sydney - - name: clusterGroup.isHubCluster - value: "false" - destination: - name: sydney - namespace: mypattern-argo-edge - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: clustergroup/templates/plumbing/hosted-sites.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: mypattern-argo-edge-sydney-plumbing - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - project: argo-edge - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-argo-edge.yaml" - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: mypattern - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.localClusterDomain - value: apps.syd.beekhof.net - - name: global.clusterDomain - value: syd.beekhof.net - - name: enabled - value: plumbing - - name: clusterGroup.name - value: argo-edge - - name: clusterGroup.targetCluster - value: sydney - - name: clusterGroup.hostedSite.secretsPath - value: secret/data/hub/cluster_sydney - - name: clusterGroup.isHubCluster - value: "false" - destination: - name: in-cluster - namespace: openshift-gitops - syncPolicy: - automated: - selfHeal: true - ignoreDifferences: - - group: apps - kind: Deployment - jsonPointers: - - /spec/replicas - - group: route.openshift.io - kind: Route - jsonPointers: - - /status ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - finalizers: - - argoproj.io/finalizer - # Changing the name affects the ClusterRoleBinding, the generated secret, - # route URL, and argocd.argoproj.io/managed-by annotations - name: example-gitops - namespace: mypattern-example - annotations: - argocd.argoproj.io/compare-options: IgnoreExtraneous -spec: -# Adding health checks to argocd to prevent pvc resources -# that aren't bound state from blocking deployments - resourceHealthChecks: - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - - applicationInstanceLabelKey: argocd.argoproj.io/instance - applicationSet: - resources: - limits: - cpu: "2" - memory: 1Gi - requests: - cpu: 250m - memory: 512Mi - controller: - processors: {} - resources: - limits: - cpu: "4" - memory: 4Gi - requests: - cpu: 500m - memory: 2Gi - sso: - provider: dex - dex: - openShiftOAuth: true - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 250m - memory: 128Mi - initialSSHKnownHosts: {} - rbac: - defaultPolicy: role:admin - repo: - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun - server: - autoscale: - enabled: false - grpc: - ingress: - enabled: false - ingress: - enabled: false - resources: - limits: - cpu: 500m - memory: 256Mi - requests: - cpu: 125m - memory: 128Mi - route: - enabled: true - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - service: - type: "" - tls: - ca: {} -status: ---- -# Source: clustergroup/templates/plumbing/argocd.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: example-gitops-link - namespace: mypattern-example -spec: - applicationMenu: - section: OpenShift GitOps - imageURL: data:image/png;base64,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 - href: 'https://example-gitops-server-mypattern-example.apps.region.example.com' - location: ApplicationMenu - text: 'Example ArgoCD' ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: application-ci-operator-group - namespace: application-ci -spec: - targetNamespaces: - - application-ci - - other-namespace ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: exclude-targetns-operator-group - namespace: exclude-targetns -spec: - targetNamespaces: ---- -# Source: clustergroup/templates/core/operatorgroup.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: include-ci-operator-group - namespace: include-ci -spec: - targetNamespaces: - - include-ci ---- -# Source: clustergroup/templates/core/operatorgroup.yaml ---- -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: include-default-og-operator-group - namespace: include-default-og -spec: - targetNamespaces: - - include-default-og ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: advanced-cluster-management - namespace: open-cluster-management -spec: - name: advanced-cluster-management - source: redhat-operators - sourceNamespace: openshift-marketplace - channel: release-2.4 - installPlanApproval: Automatic - startingCSV: advanced-cluster-management.v2.4.1 ---- -# Source: clustergroup/templates/core/subscriptions.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-pipelines-operator-rh - namespace: openshift-operators -spec: - name: openshift-pipelines-operator-rh - source: redhat-operators - sourceNamespace: openshift-marketplace - installPlanApproval: Automatic - startingCSV: redhat-openshift-pipelines.v1.5.2 diff --git a/tests/common-examples-blank-naked.expected.yaml b/tests/common-examples-blank-naked.expected.yaml deleted file mode 100644 index 51a92e5d..00000000 --- a/tests/common-examples-blank-naked.expected.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -# Source: blank/templates/manifest.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: example diff --git a/tests/common-examples-blank-normal.expected.yaml b/tests/common-examples-blank-normal.expected.yaml deleted file mode 100644 index 51a92e5d..00000000 --- a/tests/common-examples-blank-normal.expected.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -# Source: blank/templates/manifest.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: example diff --git a/tests/common-examples-kustomize-renderer-naked.expected.yaml b/tests/common-examples-kustomize-renderer-naked.expected.yaml deleted file mode 100644 index 0aa7ee5d..00000000 --- a/tests/common-examples-kustomize-renderer-naked.expected.yaml +++ /dev/null @@ -1,36 +0,0 @@ ---- -# Source: example/templates/environment.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: environment -data: - IMAGE_PROVIDER: - IMAGE_ACCOUNT: PLAINTEXT - GIT_EMAIL: SOMEWHERE@EXAMPLE.COM - GIT_DEV_REPO_URL: https:///PLAINTEXT/manuela-dev.git - GIT_DEV_REPO_REVISION: main - GIT_OPS_REPO_TEST_URL: - GIT_OPS_REPO_TEST_REVISION: - GIT_OPS_REPO_PROD_URL: - GIT_OPS_REPO_PROD_REVISION: - IOT_CONSUMER_IMAGE: iot-consumer - IOT_CONSUMER_YAML_PATH: images.(name==messaging).newTag - IOT_CONSUMER_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_CONSUMER_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/messaging/kustomization.yaml - IOT_CONSUMER_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/messaging/messaging-is.yaml - IOT_FRONTEND_IMAGE: iot-frontend - IOT_FRONTEND_YAML_PATH: images.(name==line-dashboard).newTag - IOT_FRONTEND_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_FRONTEND_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/line-dashboard/kustomization.yaml - IOT_FRONTEND_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/line-dashboard/line-dashboard-is.yaml - IOT_SWSENSOR_IMAGE: iot-software-sensor - IOT_SWSENSOR_YAML_PATH: images.(name==machine-sensor).newTag - IOT_SWSENSOR_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_SWSENSOR_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/machine-sensor/kustomization.yaml - IOT_SWSENSOR_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/machine-sensor/machine-sensor-is.yaml - IOT_ANOMALY_IMAGE: iot-anomaly-detection - IOT_ANOMALY_YAML_PATH: images.(name==anomaly-detection).newTag - IOT_ANOMALY_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_ANOMALY_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/anomaly-detection/kustomization.yaml - IOT_ANOMALY_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/anomaly-detection/anomaly-detection-is.yaml diff --git a/tests/common-examples-kustomize-renderer-normal.expected.yaml b/tests/common-examples-kustomize-renderer-normal.expected.yaml deleted file mode 100644 index caa4c08d..00000000 --- a/tests/common-examples-kustomize-renderer-normal.expected.yaml +++ /dev/null @@ -1,36 +0,0 @@ ---- -# Source: example/templates/environment.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: environment -data: - IMAGE_PROVIDER: - IMAGE_ACCOUNT: PLAINTEXT - GIT_EMAIL: SOMEWHERE@EXAMPLE.COM - GIT_DEV_REPO_URL: https:///PLAINTEXT/manuela-dev.git - GIT_DEV_REPO_REVISION: main - GIT_OPS_REPO_TEST_URL: https://github.com/pattern-clone/mypattern - GIT_OPS_REPO_TEST_REVISION: - GIT_OPS_REPO_PROD_URL: https://github.com/pattern-clone/mypattern - GIT_OPS_REPO_PROD_REVISION: - IOT_CONSUMER_IMAGE: iot-consumer - IOT_CONSUMER_YAML_PATH: images.(name==messaging).newTag - IOT_CONSUMER_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_CONSUMER_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/messaging/kustomization.yaml - IOT_CONSUMER_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/messaging/messaging-is.yaml - IOT_FRONTEND_IMAGE: iot-frontend - IOT_FRONTEND_YAML_PATH: images.(name==line-dashboard).newTag - IOT_FRONTEND_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_FRONTEND_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/line-dashboard/kustomization.yaml - IOT_FRONTEND_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/line-dashboard/line-dashboard-is.yaml - IOT_SWSENSOR_IMAGE: iot-software-sensor - IOT_SWSENSOR_YAML_PATH: images.(name==machine-sensor).newTag - IOT_SWSENSOR_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_SWSENSOR_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/machine-sensor/kustomization.yaml - IOT_SWSENSOR_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/machine-sensor/machine-sensor-is.yaml - IOT_ANOMALY_IMAGE: iot-anomaly-detection - IOT_ANOMALY_YAML_PATH: images.(name==anomaly-detection).newTag - IOT_ANOMALY_TEST_KUSTOMIZATION_PATH: charts/datacenter/manuela-tst/kustomization.yaml - IOT_ANOMALY_PROD_KUSTOMIZATION_PATH: charts/factory/manuela-stormshift/anomaly-detection/kustomization.yaml - IOT_ANOMALY_PROD_IMAGESTREAM_PATH: charts/factory/manuela-stormshift/anomaly-detection/anomaly-detection-is.yaml diff --git a/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml deleted file mode 100644 index 441ce4ca..00000000 --- a/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,11835 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: The labels to select by to find the Namespaces to create the ExternalSecrets in. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-controller -subjects: - - name: common-golang-external-secrets - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: common-golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: common-golang-external-secrets - namespace: "default" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=common-golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=common-golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: common-golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=common-golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: common-golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.apps.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: Secret - name: hub-ca - key: hub-kube-root-ca.crt - namespace: imperative - - auth: - kubernetes: - - mountPath: region.example.com - role: region.example.com-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml b/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml deleted file mode 100644 index 439dcf7f..00000000 --- a/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,11835 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: The labels to select by to find the Namespaces to create the ExternalSecrets in. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-controller -subjects: - - name: common-golang-external-secrets - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: common-golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: common-golang-external-secrets - namespace: "default" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=common-golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=common-golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: common-golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=common-golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: common-golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.apps.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: ConfigMap - name: kube-root-ca.crt - key: ca.crt - namespace: golang-external-secrets - - auth: - kubernetes: - - mountPath: hub - role: hub-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml b/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index 439dcf7f..00000000 --- a/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,11835 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: The labels to select by to find the Namespaces to create the ExternalSecrets in. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-controller -subjects: - - name: common-golang-external-secrets - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: common-golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: common-golang-external-secrets - namespace: "default" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=common-golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=common-golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: common-golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=common-golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: common-golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.apps.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: ConfigMap - name: kube-root-ca.crt - key: ca.crt - namespace: golang-external-secrets - - auth: - kubernetes: - - mountPath: hub - role: hub-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/common-golang-external-secrets-naked.expected.yaml b/tests/common-golang-external-secrets-naked.expected.yaml deleted file mode 100644 index ef22683b..00000000 --- a/tests/common-golang-external-secrets-naked.expected.yaml +++ /dev/null @@ -1,11835 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: The labels to select by to find the Namespaces to create the ExternalSecrets in. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-controller -subjects: - - name: common-golang-external-secrets - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: common-golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: common-golang-external-secrets - namespace: "default" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=common-golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=common-golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: common-golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=common-golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: common-golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: ConfigMap - name: kube-root-ca.crt - key: ca.crt - namespace: golang-external-secrets - - auth: - kubernetes: - - mountPath: hub - role: hub-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/common-golang-external-secrets-normal.expected.yaml b/tests/common-golang-external-secrets-normal.expected.yaml deleted file mode 100644 index 439dcf7f..00000000 --- a/tests/common-golang-external-secrets-normal.expected.yaml +++ /dev/null @@ -1,11835 +0,0 @@ ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: v1 -kind: Secret -metadata: - name: golang-external-secrets - namespace: golang-external-secrets - annotations: - kubernetes.io/service-account.name: golang-external-secrets -type: kubernetes.io/service-account-token ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/acraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: acraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - acraccesstoken - kind: ACRAccessToken - listKind: ACRAccessTokenList - plural: acraccesstokens - shortNames: - - acraccesstoken - singular: acraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ACRAccessToken returns a Azure Container Registry token - that can be used for pushing/pulling images. - Note: by default it will return an ACR Refresh Token with full access - (depending on the identity). - This can be scoped down to the repository level using .spec.scope. - In case scope is defined it will return an ACR Access Token. - - - See docs: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ACRAccessTokenSpec defines how to generate the access token - e.g. how to authenticate and which registry to use. - see: https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#overview - properties: - auth: - properties: - managedIdentity: - description: ManagedIdentity uses Azure Managed Identity to authenticate with Azure. - properties: - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - type: object - servicePrincipal: - description: ServicePrincipal uses Azure Service Principal credentials to authenticate with Azure. - properties: - secretRef: - description: |- - Configuration used to authenticate with Azure using static - credentials stored in a Kind=Secret. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - workloadIdentity: - description: WorkloadIdentity uses Azure Workload Identity to authenticate with Azure. - properties: - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - type: object - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - registry: - description: |- - the domain name of the ACR registry - e.g. foobarexample.azurecr.io - type: string - scope: - description: |- - Define the scope for the access token, e.g. pull/push access for a repository. - if not provided it will return a refresh token that has full scope. - Note: you need to pin it down to the repository level, there is no wildcard available. - - - examples: - repository:my-repository:pull,push - repository:my-repository:pull - - - see docs for details: https://docs.docker.com/registry/spec/auth/scope/ - type: string - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - required: - - auth - - registry - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clusterexternalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clusterexternalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterExternalSecret - listKind: ClusterExternalSecretList - plural: clusterexternalsecrets - shortNames: - - ces - singular: clusterexternalsecret - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .spec.externalSecretSpec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshTime - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. - properties: - externalSecretMetadata: - description: The metadata of the external secrets to be created - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - externalSecretName: - description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret - type: string - externalSecretSpec: - description: The spec for the ExternalSecrets to be created - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - namespaceSelector: - description: The labels to select by to find the Namespaces to create the ExternalSecrets in. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. - items: - type: string - type: array - refreshTime: - description: The time in which the controller should reconcile its objects and recheck namespaces for labels. - type: string - required: - - externalSecretSpec - type: object - status: - description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. - properties: - conditions: - items: - properties: - message: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - externalSecretName: - description: ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret - type: string - failedNamespaces: - description: Failed namespaces are the namespaces that failed to apply an ExternalSecret - items: - description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. - properties: - namespace: - description: Namespace is the namespace that failed when trying to apply an ExternalSecret - type: string - reason: - description: Reason is why the ExternalSecret failed to apply to the namespace - type: string - required: - - namespace - type: object - type: array - provisionedNamespaces: - description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/clustersecretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: clustersecretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ClusterSecretStore - listKind: ClusterSecretStoreList - plural: clustersecretstores - shortNames: - - css - singular: clustersecretstore - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/ecrauthorizationtoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: ecrauthorizationtokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - ecrauthorizationtoken - kind: ECRAuthorizationToken - listKind: ECRAuthorizationTokenList - plural: ecrauthorizationtokens - shortNames: - - ecrauthorizationtoken - singular: ecrauthorizationtoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an - authorization token. - The authorization token is valid for 12 hours. - The authorizationToken returned is a base64 encoded string that can be decoded - and used in a docker login command to authenticate to a registry. - For more information, see Registry authentication (https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth) in the Amazon Elastic Container Registry User Guide. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines how to authenticate with AWS - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: Region specifies the region to operate in. - type: string - role: - description: |- - You can assume a role before making calls to the - desired AWS service. - type: string - required: - - region - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/externalsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: externalsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: ExternalSecret - listKind: ExternalSecretList - plural: externalsecrets - shortNames: - - es - singular: externalsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - type: string - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - description: ExternalSecretDataRemoteRef defines Provider data location. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Merge - - None - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v1 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - maxProperties: 1 - minProperties: 1 - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - type: object - type: array - type: - type: string - type: object - type: object - required: - - secretStoreRef - - target - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name - name: Store - type: string - - jsonPath: .spec.refreshInterval - name: Refresh Interval - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ExternalSecret is the Schema for the external-secrets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ExternalSecretSpec defines the desired state of ExternalSecret. - properties: - data: - description: Data defines the connection between the Kubernetes Secret keys and the Provider data - items: - description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. - properties: - remoteRef: - description: |- - RemoteRef points to the remote secret and defines - which secret (version/property/..) to fetch. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - secretKey: - description: |- - SecretKey defines the key in which the controller stores - the value. This is the key in the Kind=Secret - type: string - sourceRef: - description: |- - SourceRef allows you to override the source - from which the value will pulled from. - maxProperties: 1 - properties: - generatorRef: - description: |- - GeneratorRef points to a generator custom resource. - - - Deprecated: The generatorRef is not implemented in .data[]. - this will be removed with v1. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - required: - - remoteRef - - secretKey - type: object - type: array - dataFrom: - description: |- - DataFrom is used to fetch all properties from a specific Provider data - If multiple entries are specified, the Secret keys are merged in the specified order - items: - properties: - extract: - description: |- - Used to extract multiple key/value pairs from one secret - Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - key: - description: Key is the key used in the Provider, mandatory - type: string - metadataPolicy: - default: None - description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None - enum: - - None - - Fetch - type: string - property: - description: Used to select a specific property of the Provider value (if a map), if supported - type: string - version: - description: Used to select a specific version of the Provider value, if supported - type: string - required: - - key - type: object - find: - description: |- - Used to find secrets based on tags or regular expressions - Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef. - properties: - conversionStrategy: - default: Default - description: Used to define a conversion Strategy - enum: - - Default - - Unicode - type: string - decodingStrategy: - default: None - description: Used to define a decoding Strategy - enum: - - Auto - - Base64 - - Base64URL - - None - type: string - name: - description: Finds secrets based on the name. - properties: - regexp: - description: Finds secrets base - type: string - type: object - path: - description: A root path to start the find operations. - type: string - tags: - additionalProperties: - type: string - description: Find secrets based on tags. - type: object - type: object - rewrite: - description: |- - Used to rewrite secret Keys after getting them from the secret Provider - Multiple Rewrite operations can be provided. They are applied in a layered order (first to last) - items: - properties: - regexp: - description: |- - Used to rewrite with regular expressions. - The resulting key will be the output of a regexp.ReplaceAll operation. - properties: - source: - description: Used to define the regular expression of a re.Compiler. - type: string - target: - description: Used to define the target pattern of a ReplaceAll operation. - type: string - required: - - source - - target - type: object - transform: - description: |- - Used to apply string transformation on the secrets. - The resulting key will be the output of the template applied by the operation. - properties: - template: - description: |- - Used to define the template to apply on the secret name. - `.value ` will specify the secret name in the template. - type: string - required: - - template - type: object - type: object - type: array - sourceRef: - description: |- - SourceRef points to a store or generator - which contains secret values ready to use. - Use this in combination with Extract or Find pull values out of - a specific SecretStore. - When sourceRef points to a generator Extract or Find is not supported. - The generator returns a static map of values - maxProperties: 1 - properties: - generatorRef: - description: GeneratorRef points to a generator custom resource. - properties: - apiVersion: - default: generators.external-secrets.io/v1alpha1 - description: Specify the apiVersion of the generator resource - type: string - kind: - description: Specify the Kind of the resource, e.g. Password, ACRAccessToken etc. - type: string - name: - description: Specify the name of the generator resource - type: string - required: - - kind - - name - type: object - storeRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - type: object - type: object - type: array - refreshInterval: - default: 1h - description: |- - RefreshInterval is the amount of time before the values are read again from the SecretStore provider - Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" - May be set to zero to fetch and create it once. Defaults to 1h. - type: string - secretStoreRef: - description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. - properties: - kind: - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - name: - description: Name of the SecretStore resource - type: string - required: - - name - type: object - target: - default: - creationPolicy: Owner - deletionPolicy: Retain - description: |- - ExternalSecretTarget defines the Kubernetes Secret to be created - There can be only one target per ExternalSecret. - properties: - creationPolicy: - default: Owner - description: |- - CreationPolicy defines rules on how to create the resulting Secret - Defaults to 'Owner' - enum: - - Owner - - Orphan - - Merge - - None - type: string - deletionPolicy: - default: Retain - description: |- - DeletionPolicy defines rules on how to delete the resulting Secret - Defaults to 'Retain' - enum: - - Delete - - Merge - - Retain - type: string - immutable: - description: Immutable defines if the final secret will be immutable - type: boolean - name: - description: |- - Name defines the name of the Secret resource to be managed - This field is immutable - Defaults to the .metadata.name of the ExternalSecret resource - type: string - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - type: object - type: object - status: - properties: - binding: - description: Binding represents a servicebinding.io Provisioned Service reference to the secret - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/fake.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: fakes.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - fake - kind: Fake - listKind: FakeList - plural: fakes - shortNames: - - fake - singular: fake - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Fake generator is used for testing. It lets you define - a static set of credentials that is always returned. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FakeSpec contains the static data. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - data: - additionalProperties: - type: string - description: |- - Data defines the static data returned - by this generator. - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/gcraccesstoken.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: gcraccesstokens.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - gcraccesstoken - kind: GCRAccessToken - listKind: GCRAccessTokenList - plural: gcraccesstokens - shortNames: - - gcraccesstoken - singular: gcraccesstoken - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - GCRAccessToken generates an GCP access token - that can be used to authenticate with GCR. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - auth: - description: Auth defines the means for authenticating with GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID defines which project to use to authenticate with - type: string - required: - - auth - - projectID - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/password.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: passwords.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - password - kind: Password - listKind: PasswordList - plural: passwords - shortNames: - - password - singular: password - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Password generates a random password based on the - configuration parameters in spec. - You can specify the length, characterset and other attributes. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PasswordSpec controls the behavior of the password generator. - properties: - allowRepeat: - default: false - description: set AllowRepeat to true to allow repeating characters. - type: boolean - digits: - description: |- - Digits specifies the number of digits in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - length: - default: 24 - description: |- - Length of the password to be generated. - Defaults to 24 - type: integer - noUpper: - default: false - description: Set NoUpper to disable uppercase characters - type: boolean - symbolCharacters: - description: |- - SymbolCharacters specifies the special characters that should be used - in the generated password. - type: string - symbols: - description: |- - Symbols specifies the number of symbol characters in the generated - password. If omitted it defaults to 25% of the length of the password - type: integer - required: - - allowRepeat - - length - - noUpper - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/pushsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: pushsecrets.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - pushsecrets - kind: PushSecret - listKind: PushSecretList - plural: pushsecrets - singular: pushsecret - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PushSecretSpec configures the behavior of the PushSecret. - properties: - data: - description: Secret Data that should be pushed to providers - items: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: array - deletionPolicy: - default: None - description: 'Deletion Policy to handle Secrets in the provider. Possible Values: "Delete/None". Defaults to "None".' - enum: - - Delete - - None - type: string - refreshInterval: - description: The Interval to which External Secrets will try to push a secret definition - type: string - secretStoreRefs: - items: - properties: - kind: - default: SecretStore - description: |- - Kind of the SecretStore resource (SecretStore or ClusterSecretStore) - Defaults to `SecretStore` - type: string - labelSelector: - description: Optionally, sync to secret stores with label selector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Optionally, sync to the SecretStore of the given name - type: string - type: object - type: array - selector: - description: The Secret Selector (k8s source) for the Push Secret - properties: - secret: - description: Select a Secret to Push. - properties: - name: - description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest. - type: string - required: - - name - type: object - required: - - secret - type: object - template: - description: Template defines a blueprint for the created Secret resource. - properties: - data: - additionalProperties: - type: string - type: object - engineVersion: - default: v2 - description: |- - EngineVersion specifies the template engine version - that should be used to compile/execute the - template specified in .data and .templateFrom[]. - enum: - - v1 - - v2 - type: string - mergePolicy: - default: Replace - enum: - - Replace - - Merge - type: string - metadata: - description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - templateFrom: - items: - properties: - configMap: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - literal: - type: string - secret: - properties: - items: - items: - properties: - key: - type: string - templateAs: - default: Values - enum: - - Values - - KeysAndValues - type: string - required: - - key - type: object - type: array - name: - type: string - required: - - items - - name - type: object - target: - default: Data - enum: - - Data - - Annotations - - Labels - type: string - type: object - type: array - type: - type: string - type: object - required: - - secretStoreRefs - - selector - type: object - status: - description: PushSecretStatus indicates the history of the status of PushSecret. - properties: - conditions: - items: - description: PushSecretStatusCondition indicates the status of the PushSecret. - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - description: PushSecretConditionType indicates the condition of the PushSecret. - type: string - required: - - status - - type - type: object - type: array - refreshTime: - description: |- - refreshTime is the time and date the external secret was fetched and - the target secret updated - format: date-time - nullable: true - type: string - syncedPushSecrets: - additionalProperties: - additionalProperties: - properties: - match: - description: Match a given Secret Key to be pushed to the provider. - properties: - remoteRef: - description: Remote Refs to push to providers. - properties: - property: - description: Name of the property in the resulting secret - type: string - remoteKey: - description: Name of the resulting provider secret. - type: string - required: - - remoteKey - type: object - secretKey: - description: Secret Key to be pushed - type: string - required: - - remoteRef - type: object - metadata: - description: |- - Metadata is metadata attached to the secret. - The structure of metadata is provider specific, please look it up in the provider documentation. - x-kubernetes-preserve-unknown-fields: true - required: - - match - type: object - type: object - description: Synced Push Secrets for later deletion. Matches Secret Stores to PushSecretData that was stored to that secretStore. - type: object - syncedResourceVersion: - description: SyncedResourceVersion keeps track of the last synced version. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/secretstore.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: secretstores.external-secrets.io -spec: - group: external-secrets.io - names: - categories: - - externalsecrets - kind: SecretStore - listKind: SecretStoreList - plural: secretstores - shortNames: - - ss - singular: secretstore - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - deprecated: true - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the SecretManager provider will assume - type: string - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - properties: - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - secretRef - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - serviceAccount: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, instance principal is used. Optionally, the authenticating principal type - and/or user data may be supplied for the use of workload identity and user principal. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - roleId - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - - jsonPath: .status.capabilities - name: Capabilities - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: SecretStoreSpec defines the desired state of SecretStore. - properties: - conditions: - description: Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore - items: - description: |- - ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in - for a ClusterSecretStore instance. - properties: - namespaceSelector: - description: Choose namespace using a labelSelector - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: Choose namespaces by name - items: - type: string - type: array - type: object - type: array - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters ES based on this property - type: string - provider: - description: Used to configure the provider. Only one provider may be set - maxProperties: 1 - minProperties: 1 - properties: - akeyless: - description: Akeyless configures this store to sync secrets using Akeyless Vault provider - properties: - akeylessGWApiURL: - description: Akeyless GW API Url from which the secrets to be fetched from. - type: string - authSecretRef: - description: Auth configures how the operator authenticates with Akeyless. - properties: - kubernetesAuth: - description: |- - Kubernetes authenticates with Akeyless by passing the ServiceAccount - token stored in the named Secret resource. - properties: - accessID: - description: the Akeyless Kubernetes auth-method access-id - type: string - k8sConfName: - description: Kubernetes-auth configuration name in Akeyless-Gateway - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Akeyless. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Akeyless. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - accessID - - k8sConfName - type: object - secretRef: - description: |- - Reference to a Secret that contains the details - to authenticate with Akeyless. - properties: - accessID: - description: The SecretAccessID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessType: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessTypeParam: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - caBundle: - description: |- - PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used - if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Akeyless Gateway certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - required: - - akeylessGWApiURL - - authSecretRef - type: object - alibaba: - description: Alibaba configures this store to sync secrets using Alibaba Cloud provider - properties: - auth: - description: AlibabaAuth contains a secretRef for credentials. - properties: - rrsa: - description: Authenticate against Alibaba using RRSA. - properties: - oidcProviderArn: - type: string - oidcTokenFilePath: - type: string - roleArn: - type: string - sessionName: - type: string - required: - - oidcProviderArn - - oidcTokenFilePath - - roleArn - - sessionName - type: object - secretRef: - description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - accessKeySecretSecretRef: - description: The AccessKeySecret is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - accessKeyIDSecretRef - - accessKeySecretSecretRef - type: object - type: object - regionID: - description: Alibaba Region to be used for the provider - type: string - required: - - auth - - regionID - type: object - aws: - description: AWS configures this store to sync secrets using AWS Secret Manager provider - properties: - additionalRoles: - description: AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role - items: - type: string - type: array - auth: - description: |- - Auth defines the information necessary to authenticate against AWS - if not set aws sdk will infer credentials from your environment - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - jwt: - description: Authenticate against AWS using service account tokens. - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - secretRef: - description: |- - AWSAuthSecretRef holds secret references for AWS credentials - both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - externalID: - description: AWS External ID set on assumed IAM roles - type: string - region: - description: AWS Region to be used for the provider - type: string - role: - description: Role is a Role ARN which the provider will assume - type: string - secretsManager: - description: SecretsManager defines how the provider behaves when interacting with AWS SecretsManager - properties: - forceDeleteWithoutRecovery: - description: |- - Specifies whether to delete the secret without any recovery window. You - can't use both this parameter and RecoveryWindowInDays in the same call. - If you don't use either, then by default Secrets Manager uses a 30 day - recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery - type: boolean - recoveryWindowInDays: - description: |- - The number of days from 7 to 30 that Secrets Manager waits before - permanently deleting the secret. You can't use both this parameter and - ForceDeleteWithoutRecovery in the same call. If you don't use either, - then by default Secrets Manager uses a 30 day recovery window. - see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays - format: int64 - type: integer - type: object - service: - description: Service defines which service should be used to fetch the secrets - enum: - - SecretsManager - - ParameterStore - type: string - sessionTags: - description: AWS STS assume role session tags - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - transitiveTagKeys: - description: AWS STS assume role transitive session tags. Required when multiple rules are used with the provider - items: - type: string - type: array - required: - - region - - service - type: object - azurekv: - description: AzureKV configures this store to sync secrets using Azure Key Vault provider - properties: - authSecretRef: - description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. - properties: - clientId: - description: The Azure clientId of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientSecret: - description: The Azure ClientSecret of the service principle used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - authType: - default: ServicePrincipal - description: |- - Auth type defines how to authenticate to the keyvault service. - Valid values are: - - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity) - enum: - - ServicePrincipal - - ManagedIdentity - - WorkloadIdentity - type: string - environmentType: - default: PublicCloud - description: |- - EnvironmentType specifies the Azure cloud environment endpoints to use for - connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. - The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 - PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud - enum: - - PublicCloud - - USGovernmentCloud - - ChinaCloud - - GermanCloud - type: string - identityId: - description: If multiple Managed Identity is assigned to the pod, you can select the one to be used - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - tenantId: - description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. - type: string - vaultUrl: - description: Vault Url from which the secrets to be fetched from. - type: string - required: - - vaultUrl - type: object - chef: - description: Chef configures this store to sync secrets with chef server - properties: - auth: - description: Auth defines the information necessary to authenticate against chef Server - properties: - secretRef: - description: ChefAuthSecretRef holds secret references for chef server login credentials. - properties: - privateKeySecretRef: - description: SecretKey is the Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - privateKeySecretRef - type: object - required: - - secretRef - type: object - serverUrl: - description: ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/" - type: string - username: - description: UserName should be the user ID on the chef server - type: string - required: - - auth - - serverUrl - - username - type: object - conjur: - description: Conjur configures this store to sync secrets using conjur provider - properties: - auth: - properties: - apikey: - properties: - account: - type: string - apiKeyRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - account - - apiKeyRef - - userRef - type: object - jwt: - properties: - account: - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Conjur using the JWT authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional ServiceAccountRef specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - serviceID: - description: The conjur authn jwt webservice id - type: string - required: - - account - - serviceID - type: object - type: object - caBundle: - type: string - caProvider: - description: |- - Used to provide custom certificate authority (CA) certificates - for a secret store. The CAProvider points to a Secret or ConfigMap resource - that contains a PEM-encoded certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - type: string - required: - - auth - - url - type: object - delinea: - description: |- - Delinea DevOps Secrets Vault - https://docs.delinea.com/online-help/products/devops-secrets-vault/current - properties: - clientId: - description: ClientID is the non-secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - clientSecret: - description: ClientSecret is the secret part of the credential. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - tenant: - description: Tenant is the chosen hostname / site name. - type: string - tld: - description: |- - TLD is based on the server location that was chosen during provisioning. - If unset, defaults to "com". - type: string - urlTemplate: - description: |- - URLTemplate - If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". - type: string - required: - - clientId - - clientSecret - - tenant - type: object - doppler: - description: Doppler configures this store to sync secrets using the Doppler provider - properties: - auth: - description: Auth configures how the Operator authenticates with the Doppler API - properties: - secretRef: - properties: - dopplerToken: - description: |- - The DopplerToken is used for authentication. - See https://docs.doppler.com/reference/api#authentication for auth token types. - The Key attribute defaults to dopplerToken if not specified. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - dopplerToken - type: object - required: - - secretRef - type: object - config: - description: Doppler config (required if not using a Service Token) - type: string - format: - description: Format enables the downloading of secrets as a file (string) - enum: - - json - - dotnet-json - - env - - yaml - - docker - type: string - nameTransformer: - description: Environment variable compatible name transforms that change secret names to a different format - enum: - - upper-camel - - camel - - lower-snake - - tf-var - - dotnet-env - - lower-kebab - type: string - project: - description: Doppler project (required if not using a Service Token) - type: string - required: - - auth - type: object - fake: - description: Fake configures a store with static key/value pairs - properties: - data: - items: - properties: - key: - type: string - value: - type: string - valueMap: - additionalProperties: - type: string - description: 'Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the `value` field instead.' - type: object - version: - type: string - required: - - key - type: object - type: array - required: - - data - type: object - gcpsm: - description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider - properties: - auth: - description: Auth defines the information necessary to authenticate against GCP - properties: - secretRef: - properties: - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - workloadIdentity: - properties: - clusterLocation: - type: string - clusterName: - type: string - clusterProjectID: - type: string - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - clusterLocation - - clusterName - - serviceAccountRef - type: object - type: object - projectID: - description: ProjectID project where secret is located - type: string - type: object - gitlab: - description: GitLab configures this store to sync secrets using GitLab Variables provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a GitLab instance. - properties: - SecretRef: - properties: - accessToken: - description: AccessToken is used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - SecretRef - type: object - environment: - description: Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments) - type: string - groupIDs: - description: GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables. - items: - type: string - type: array - inheritFromGroups: - description: InheritFromGroups specifies whether parent groups should be discovered and checked for secrets. - type: boolean - projectID: - description: ProjectID specifies a project where secrets are located. - type: string - url: - description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. - type: string - required: - - auth - type: object - ibm: - description: IBM configures this store to sync secrets using IBM Cloud provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the IBM secrets manager. - maxProperties: 1 - minProperties: 1 - properties: - containerAuth: - description: IBM Container-based auth with IAM Trusted Profile. - properties: - iamEndpoint: - type: string - profile: - description: the IBM Trusted Profile - type: string - tokenLocation: - description: Location the token is mounted on the pod - type: string - required: - - profile - type: object - secretRef: - properties: - secretApiKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - serviceUrl: - description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance - type: string - required: - - auth - type: object - keepersecurity: - description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider - properties: - authRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - folderID: - type: string - required: - - authRef - - folderID - type: object - kubernetes: - description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider - properties: - auth: - description: Auth configures how secret-manager authenticates with a Kubernetes instance. - maxProperties: 1 - minProperties: 1 - properties: - cert: - description: has both clientCert and clientKey as secretKeySelector - properties: - clientCert: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - clientKey: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - serviceAccount: - description: points to a service account that should be used for authentication - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - token: - description: use static token to authenticate with - properties: - bearerToken: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - type: object - remoteNamespace: - default: default - description: Remote namespace to fetch the secrets from - type: string - server: - description: configures the Kubernetes server Address. - properties: - caBundle: - description: CABundle is a base64-encoded CA certificate - format: byte - type: string - caProvider: - description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - url: - default: kubernetes.default - description: configures the Kubernetes server Address. - type: string - type: object - required: - - auth - type: object - onepassword: - description: OnePassword configures this store to sync secrets using the 1Password Cloud provider - properties: - auth: - description: Auth defines the information necessary to authenticate against OnePassword Connect Server - properties: - secretRef: - description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. - properties: - connectTokenSecretRef: - description: The ConnectToken is used for authentication to a 1Password Connect Server. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - connectTokenSecretRef - type: object - required: - - secretRef - type: object - connectHost: - description: ConnectHost defines the OnePassword Connect Server to connect to - type: string - vaults: - additionalProperties: - type: integer - description: Vaults defines which OnePassword vaults to search in which order - type: object - required: - - auth - - connectHost - - vaults - type: object - oracle: - description: Oracle configures this store to sync secrets using Oracle Vault provider - properties: - auth: - description: |- - Auth configures how secret-manager authenticates with the Oracle Vault. - If empty, use the instance principal, otherwise the user credentials specified in Auth. - properties: - secretRef: - description: SecretRef to pass through sensitive information. - properties: - fingerprint: - description: Fingerprint is the fingerprint of the API private key. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - privatekey: - description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - fingerprint - - privatekey - type: object - tenancy: - description: Tenancy is the tenancy OCID where user is located. - type: string - user: - description: User is an access OCID specific to the account. - type: string - required: - - secretRef - - tenancy - - user - type: object - compartment: - description: |- - Compartment is the vault compartment OCID. - Required for PushSecret - type: string - encryptionKey: - description: |- - EncryptionKey is the OCID of the encryption key within the vault. - Required for PushSecret - type: string - principalType: - description: |- - The type of principal to use for authentication. If left blank, the Auth struct will - determine the principal type. This optional field must be specified if using - workload identity. - enum: - - "" - - UserPrincipal - - InstancePrincipal - - Workload - type: string - region: - description: Region is the region where vault is located. - type: string - serviceAccountRef: - description: |- - ServiceAccountRef specified the service account - that should be used when authenticating with WorkloadIdentity. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - vault: - description: Vault is the vault's OCID of the specific vault where secret is located. - type: string - required: - - region - - vault - type: object - pulumi: - description: Pulumi configures this store to sync secrets using the Pulumi provider - properties: - accessToken: - description: AccessToken is the access tokens to sign in to the Pulumi Cloud Console. - properties: - secretRef: - description: SecretRef is a reference to a secret containing the Pulumi API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - apiUrl: - default: https://api.pulumi.com - description: APIURL is the URL of the Pulumi API. - type: string - environment: - description: |- - Environment are YAML documents composed of static key-value pairs, programmatic expressions, - dynamically retrieved values from supported providers including all major clouds, - and other Pulumi ESC environments. - To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information. - type: string - organization: - description: |- - Organization are a space to collaborate on shared projects and stacks. - To create a new organization, visit https://app.pulumi.com/ and click "New Organization". - type: string - required: - - accessToken - - environment - - organization - type: object - scaleway: - description: Scaleway - properties: - accessKey: - description: AccessKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - apiUrl: - description: APIURL is the url of the api to use. Defaults to https://api.scaleway.com - type: string - projectId: - description: 'ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings' - type: string - region: - description: 'Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone' - type: string - secretKey: - description: SecretKey is the non-secret part of the api key. - properties: - secretRef: - description: SecretRef references a key in a secret that will be used as value. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - value: - description: Value can be specified directly to set a value without using a secret. - type: string - type: object - required: - - accessKey - - projectId - - region - - secretKey - type: object - senhasegura: - description: Senhasegura configures this store to sync secrets using senhasegura provider - properties: - auth: - description: Auth defines parameters to authenticate in senhasegura - properties: - clientId: - type: string - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - clientId - - clientSecretSecretRef - type: object - ignoreSslCertificate: - default: false - description: IgnoreSslCertificate defines if SSL certificate must be ignored - type: boolean - module: - description: Module defines which senhasegura module should be used to get secrets - type: string - url: - description: URL of senhasegura - type: string - required: - - auth - - module - - url - type: object - vault: - description: Vault configures this store to sync secrets using Hashi provider - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - webhook: - description: Webhook configures this store to sync secrets using a generic templated webhook - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - yandexcertificatemanager: - description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Certificate Manager - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - yandexlockbox: - description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider - properties: - apiEndpoint: - description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') - type: string - auth: - description: Auth defines the information necessary to authenticate against Yandex Lockbox - properties: - authorizedKeySecretRef: - description: The authorized key used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - caProvider: - description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. - properties: - certSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource, - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - required: - - auth - type: object - type: object - refreshInterval: - description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. - type: integer - retrySettings: - description: Used to configure http retries if failed - properties: - maxRetries: - format: int32 - type: integer - retryInterval: - type: string - type: object - required: - - provider - type: object - status: - description: SecretStoreStatus defines the observed state of the SecretStore. - properties: - capabilities: - description: SecretStoreCapabilities defines the possible operations a SecretStore can do. - type: string - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/vaultdynamicsecret.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: vaultdynamicsecrets.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - vaultdynamicsecret - kind: VaultDynamicSecret - listKind: VaultDynamicSecretList - plural: vaultdynamicsecrets - shortNames: - - vaultdynamicsecret - singular: vaultdynamicsecret - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - controller: - description: |- - Used to select the correct ESO controller (think: ingress.ingressClassName) - The ESO controller is instantiated with a specific controller name and filters VDS based on this property - type: string - method: - description: Vault API method to use (GET/POST/other) - type: string - parameters: - description: Parameters to pass to Vault write (for non-GET methods) - x-kubernetes-preserve-unknown-fields: true - path: - description: Vault path to obtain the dynamic secret from - type: string - provider: - description: Vault provider common spec - properties: - auth: - description: Auth configures how secret-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - default: approle - description: |- - Path where the App Role authentication backend is mounted - in Vault, e.g: "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - roleRef: - description: |- - Reference to a key in a Secret that contains the App Role ID used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role id. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - - secretRef - type: object - cert: - description: |- - Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate - Cert authentication method - properties: - clientCert: - description: |- - ClientCert is a certificate to authenticate using the Cert Vault - authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretRef: - description: |- - SecretRef to a key in a Secret resource containing client private key to - authenticate with Vault using the Cert authentication method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - iam: - description: |- - Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials - AWS IAM authentication method - properties: - externalID: - description: AWS External ID set on assumed IAM roles - type: string - jwt: - description: Specify a service account with IRSA enabled - properties: - serviceAccountRef: - description: A reference to a ServiceAccount resource. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - type: object - path: - description: 'Path where the AWS auth method is enabled in Vault, e.g: "aws"' - type: string - region: - description: AWS region - type: string - role: - description: This is the AWS role to be assumed before talking to vault - type: string - secretRef: - description: Specify credentials in a Secret object - properties: - accessKeyIDSecretRef: - description: The AccessKeyID is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - secretAccessKeySecretRef: - description: The SecretAccessKey is used for authentication - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - sessionTokenSecretRef: - description: |- - The SessionToken used for authentication - This must be defined if AccessKeyID and SecretAccessKey are temporary credentials - see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - vaultAwsIamServerID: - description: 'X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws' - type: string - vaultRole: - description: Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine - type: string - required: - - vaultRole - type: object - jwt: - description: |- - Jwt authenticates with Vault by passing role and JWT token using the - JWT/OIDC authentication method - properties: - kubernetesServiceAccountToken: - description: |- - Optional ServiceAccountToken specifies the Kubernetes service account for which to request - a token for with the `TokenRequest` API. - properties: - audiences: - description: |- - Optional audiences field that will be used to request a temporary Kubernetes service - account token for the service account referenced by `serviceAccountRef`. - Defaults to a single audience `vault` it not specified. - Deprecated: use serviceAccountRef.Audiences instead - items: - type: string - type: array - expirationSeconds: - description: |- - Optional expiration time in seconds that will be used to request a temporary - Kubernetes service account token for the service account referenced by - `serviceAccountRef`. - Deprecated: this will be removed in the future. - Defaults to 10 minutes. - format: int64 - type: integer - serviceAccountRef: - description: Service account field containing the name of a kubernetes ServiceAccount. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - path: - default: jwt - description: |- - Path where the JWT authentication backend is mounted - in Vault, e.g: "jwt" - type: string - role: - description: |- - Role is a JWT role to authenticate using the JWT/OIDC Vault - authentication method - type: string - secretRef: - description: |- - Optional SecretRef that refers to a key in a Secret resource containing JWT token to - authenticate with Vault using the JWT/OIDC authentication method. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - required: - - path - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - default: kubernetes - description: |- - Path where the Kubernetes authentication backend is mounted in Vault, e.g: - "kubernetes" - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - Optional secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. If a name is specified without a key, - `token` is the default. If one is not specified, the one bound to - the controller will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - serviceAccountRef: - description: |- - Optional service account field containing the name of a kubernetes ServiceAccount. - If the service account is specified, the service account secret token JWT will be used - for authenticating with Vault. If the service account selector is not supplied, - the secretRef will be used instead. - properties: - audiences: - description: |- - Audience specifies the `aud` claim for the service account token - If the service account uses a well-known annotation for e.g. IRSA or GCP Workload Identity - then this audiences will be appended to the list - items: - type: string - type: array - name: - description: The name of the ServiceAccount resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - required: - - name - type: object - required: - - mountPath - - role - type: object - ldap: - description: |- - Ldap authenticates with Vault by passing username/password pair using - the LDAP authentication method - properties: - path: - default: ldap - description: |- - Path where the LDAP authentication backend is mounted - in Vault, e.g: "ldap" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the LDAP - user used to authenticate with Vault using the LDAP authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a LDAP user name used to authenticate using the LDAP Vault - authentication method - type: string - required: - - path - - username - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - userPass: - description: UserPass authenticates with Vault by passing username/password pair - properties: - path: - default: user - description: |- - Path where the UserPassword authentication backend is mounted - in Vault, e.g: "user" - type: string - secretRef: - description: |- - SecretRef to a key in a Secret resource containing password for the - user used to authenticate with Vault using the UserPass authentication - method - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - username: - description: |- - Username is a user name used to authenticate using the UserPass Vault - authentication method - type: string - required: - - path - - username - type: object - type: object - caBundle: - description: |- - PEM encoded CA bundle used to validate Vault server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate Vault server certificate. - properties: - key: - description: The key where the CA certificate can be found in the Secret or ConfigMap. - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: |- - The namespace the Provider type is in. - Can only be defined when used in a ClusterSecretStore. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - forwardInconsistent: - description: |- - ForwardInconsistent tells Vault to forward read-after-write requests to the Vault - leader instead of simply retrying within a loop. This can increase performance if - the option is enabled serverside. - https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header - type: boolean - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows - Vault environments to support Secure Multi-tenancy. e.g: "ns1". - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault KV backend endpoint, e.g: - "secret". The v2 KV secret engine version specific "/data" path suffix - for fetching secrets from Vault is optional and will be appended - if not present in specified path. - type: string - readYourWrites: - description: |- - ReadYourWrites ensures isolated read-after-write semantics by - providing discovered cluster replication states in each request. - More information about eventual consistency in Vault can be found here - https://www.vaultproject.io/docs/enterprise/consistency - type: boolean - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - tls: - description: |- - The configuration used for client side related TLS communication, when the Vault server - requires mutual authentication. Only used if the Server URL is using HTTPS protocol. - This parameter is ignored for plain HTTP protocol connection. - It's worth noting this configuration is different from the "TLS certificates auth method", - which is available under the `auth.cert` section. - properties: - certSecretRef: - description: |- - CertSecretRef is a certificate added to the transport layer - when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - keySecretRef: - description: |- - KeySecretRef to a key in a Secret resource containing client private key - added to the transport layer when communicating with the Vault server. - If no key for the Secret is specified, external-secret will default to 'tls.key'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be - defaulted, in others it may be required. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - namespace: - description: |- - Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults - to the namespace of the referent. - type: string - type: object - type: object - version: - default: v2 - description: |- - Version is the Vault KV secret engine version. This can be either "v1" or - "v2". Version defaults to "v2". - enum: - - v1 - - v2 - type: string - required: - - auth - - server - type: object - resultType: - default: Data - description: |- - Result type defines which data is returned from the generator. - By default it is the "data" section of the Vault API response. - When using e.g. /auth/token/create the "data" section is empty but - the "auth" section contains the generated token. - Please refer to the vault docs regarding the result data structure. - enum: - - Data - - Auth - type: string - required: - - path - - provider - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/crds/webhook.yaml -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: webhooks.generators.external-secrets.io -spec: - group: generators.external-secrets.io - names: - categories: - - webhook - kind: Webhook - listKind: WebhookList - plural: webhooks - shortNames: - - webhookl - singular: webhook - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - Webhook connects to a third party API server to handle the secrets generation - configuration parameters in spec. - You can specify the server, the token, and additional body parameters. - See documentation for the full API specification for requests and responses. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field. - properties: - body: - description: Body - type: string - caBundle: - description: |- - PEM encoded CA bundle used to validate webhook server certificate. Only used - if the Server URL is using HTTPS protocol. This parameter is ignored for - plain HTTP protocol connection. If not set the system root certificates - are used to validate the TLS connection. - format: byte - type: string - caProvider: - description: The provider for the CA bundle to use to validate webhook server certificate. - properties: - key: - description: The key the value inside of the provider type to use, only used with "Secret" type - type: string - name: - description: The name of the object located at the provider type. - type: string - namespace: - description: The namespace the Provider type is in. - type: string - type: - description: The type of provider to use such as "Secret", or "ConfigMap". - enum: - - Secret - - ConfigMap - type: string - required: - - name - - type - type: object - headers: - additionalProperties: - type: string - description: Headers - type: object - method: - description: Webhook Method - type: string - result: - description: Result formatting - properties: - jsonPath: - description: Json path of return value - type: string - type: object - secrets: - description: |- - Secrets to fill in templates - These secrets will be passed to the templating function as key value pairs under the given name - items: - properties: - name: - description: Name of this secret in templates - type: string - secretRef: - description: Secret ref to fill in credentials - properties: - key: - description: The key where the token is found. - type: string - name: - description: The name of the Secret resource being referred to. - type: string - type: object - required: - - name - - secretRef - type: object - type: array - timeout: - description: Timeout - type: string - url: - description: Webhook url to call - type: string - required: - - result - - url - type: object - type: object - served: true - storage: true - subresources: - status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: - - v1 - clientConfig: - service: - name: common-golang-external-secrets-webhook - namespace: "default" - path: /convert ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "apiextensions.k8s.io" - resources: - - "customresourcedefinitions" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "admissionregistration.k8s.io" - resources: - - "validatingwebhookconfigurations" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "endpoints" - verbs: - - "list" - - "get" - - "watch" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "update" - - "patch" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "secretstores" - - "clustersecretstores" - - "externalsecrets" - - "clusterexternalsecrets" - - "pushsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "externalsecrets/status" - - "externalsecrets/finalizers" - - "secretstores" - - "secretstores/status" - - "secretstores/finalizers" - - "clustersecretstores" - - "clustersecretstores/status" - - "clustersecretstores/finalizers" - - "clusterexternalsecrets" - - "clusterexternalsecrets/status" - - "clusterexternalsecrets/finalizers" - - "pushsecrets" - - "pushsecrets/status" - - "pushsecrets/finalizers" - verbs: - - "update" - - "patch" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "serviceaccounts" - - "namespaces" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "get" - - "list" - - "watch" - - apiGroups: - - "" - resources: - - "secrets" - verbs: - - "get" - - "list" - - "watch" - - "create" - - "update" - - "delete" - - "patch" - - apiGroups: - - "" - resources: - - "serviceaccounts/token" - verbs: - - "create" - - apiGroups: - - "" - resources: - - "events" - verbs: - - "create" - - "patch" - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "create" - - "update" - - "delete" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-view - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-view: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "get" - - "watch" - - "list" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "get" - - "watch" - - "list" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-edit - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - - "secretstores" - - "clustersecretstores" - - "pushsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" - - apiGroups: - - "generators.external-secrets.io" - resources: - - "acraccesstokens" - - "ecrauthorizationtokens" - - "fakes" - - "gcraccesstokens" - - "passwords" - - "vaultdynamicsecrets" - verbs: - - "create" - - "delete" - - "deletecollection" - - "patch" - - "update" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: common-golang-external-secrets-servicebindings - labels: - servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "external-secrets.io" - resources: - - "externalsecrets" - verbs: - - "get" - - "list" - - "watch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-cert-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-cert-controller -subjects: - - name: external-secrets-cert-controller - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-golang-external-secrets-controller - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: common-golang-external-secrets-controller -subjects: - - name: common-golang-external-secrets - namespace: "default" - kind: ServiceAccount ---- -# Source: golang-external-secrets/templates/golang-external-secrets-hub-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: role-tokenreview-binding - namespace: default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: golang-external-secrets - namespace: golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -rules: - - apiGroups: - - "" - resources: - - "configmaps" - resourceNames: - - "external-secrets-controller" - verbs: - - "get" - - "update" - - "patch" - - apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "create" - - apiGroups: - - "coordination.k8s.io" - resources: - - "leases" - verbs: - - "get" - - "create" - - "update" - - "patch" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/rbac.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: common-golang-external-secrets-leaderelection - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: common-golang-external-secrets-leaderelection -subjects: - - kind: ServiceAccount - name: common-golang-external-secrets - namespace: "default" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - external-secrets.io/component: webhook -spec: - type: ClusterIP - ports: - - port: 443 - targetPort: 10250 - protocol: TCP - name: webhook - selector: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets ---- -# Source: golang-external-secrets/charts/external-secrets/templates/cert-controller-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-cert-controller - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-cert-controller - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: external-secrets-cert-controller - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: cert-controller - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - certcontroller - - --crd-requeue-interval=5m - - --service-name=common-golang-external-secrets-webhook - - --service-namespace=default - - --secret-name=common-golang-external-secrets-webhook - - --secret-namespace=default - - --metrics-addr=:8080 - - --healthz-addr=:8081 - - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - serviceAccountName: common-golang-external-secrets - automountServiceAccountToken: true - hostNetwork: false - containers: - - name: external-secrets - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - --concurrent=1 - - --metrics-addr=:8080 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics ---- -# Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: common-golang-external-secrets-webhook - namespace: "default" - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm -spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - template: - metadata: - labels: - helm.sh/chart: external-secrets-0.9.13 - app.kubernetes.io/name: external-secrets-webhook - app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.13" - app.kubernetes.io/managed-by: Helm - spec: - hostNetwork: false - serviceAccountName: external-secrets-webhook - automountServiceAccountToken: true - containers: - - name: webhook - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.13-ubi - imagePullPolicy: IfNotPresent - args: - - webhook - - --port=10250 - - --dns-name=common-golang-external-secrets-webhook.default.svc - - --cert-dir=/tmp/certs - - --check-interval=5m - - --metrics-addr=:8080 - - --healthz-addr=:8081 - ports: - - containerPort: 8080 - protocol: TCP - name: metrics - - containerPort: 10250 - protocol: TCP - name: webhook - readinessProbe: - httpGet: - port: 8081 - path: /readyz - initialDelaySeconds: 20 - periodSeconds: 5 - volumeMounts: - - name: certs - mountPath: /tmp/certs - readOnly: true - volumes: - - name: certs - secret: - secretName: common-golang-external-secrets-webhook ---- -# Source: golang-external-secrets/templates/vault/golang-external-secrets-hub-secretstore.yaml -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: vault-backend - namespace: golang-external-secrets -spec: - provider: - vault: - server: https://vault-vault.apps.hub.example.com - path: secret - # Version of KV backend - version: v2 - - caProvider: - type: ConfigMap - name: kube-root-ca.crt - key: ca.crt - namespace: golang-external-secrets - - auth: - kubernetes: - - mountPath: hub - role: hub-role - - secretRef: - name: golang-external-secrets - namespace: golang-external-secrets - key: "token" ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: secretstore-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.secretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["secretstores"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-secretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - -- name: "validate.clustersecretstore.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["clustersecretstores"] - scope: "Cluster" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-clustersecretstore - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 ---- -# Source: golang-external-secrets/charts/external-secrets/templates/validatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: externalsecret-validate - labels: - external-secrets.io/component: webhook -webhooks: -- name: "validate.externalsecret.external-secrets.io" - rules: - - apiGroups: ["external-secrets.io"] - apiVersions: ["v1beta1"] - operations: ["CREATE", "UPDATE", "DELETE"] - resources: ["externalsecrets"] - scope: "Namespaced" - clientConfig: - service: - namespace: "default" - name: common-golang-external-secrets-webhook - path: /validate-external-secrets-io-v1beta1-externalsecret - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None - timeoutSeconds: 5 - failurePolicy: Fail diff --git a/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml deleted file mode 100644 index 4280e75d..00000000 --- a/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,408 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: common-hashicorp-vault-config - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: common-hashicorp-vault - namespace: pattern-namespace ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-internal - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-ui - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: common-hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "common-hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: common-hashicorp-vault - - volumes: - - - name: config - configMap: - name: common-hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).common-hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.region.example.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: common-hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: common-hashicorp-vault-server-test - namespace: pattern-namespace - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://common-hashicorp-vault.pattern-namespace.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml deleted file mode 100644 index 4280e75d..00000000 --- a/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,408 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: common-hashicorp-vault-config - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: common-hashicorp-vault - namespace: pattern-namespace ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-internal - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-ui - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: common-hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "common-hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: common-hashicorp-vault - - volumes: - - - name: config - configMap: - name: common-hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).common-hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.region.example.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: common-hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: common-hashicorp-vault-server-test - namespace: pattern-namespace - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://common-hashicorp-vault.pattern-namespace.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index 4280e75d..00000000 --- a/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,408 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: common-hashicorp-vault-config - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: common-hashicorp-vault - namespace: pattern-namespace ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-internal - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-ui - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: common-hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "common-hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: common-hashicorp-vault - - volumes: - - - name: config - configMap: - name: common-hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).common-hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.region.example.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: common-hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: common-hashicorp-vault-server-test - namespace: pattern-namespace - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://common-hashicorp-vault.pattern-namespace.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/common-hashicorp-vault-naked.expected.yaml b/tests/common-hashicorp-vault-naked.expected.yaml deleted file mode 100644 index 3270df65..00000000 --- a/tests/common-hashicorp-vault-naked.expected.yaml +++ /dev/null @@ -1,408 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-hashicorp-vault - namespace: default - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: common-hashicorp-vault-config - namespace: default - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: common-hashicorp-vault - namespace: default ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-internal - namespace: default - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault - namespace: default - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-ui - namespace: default - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: common-hashicorp-vault - namespace: default - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: common-hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "common-hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: common-hashicorp-vault - - volumes: - - - name: config - configMap: - name: common-hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).common-hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.foo.cluster.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: common-hashicorp-vault - namespace: default - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: common-hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: common-hashicorp-vault-server-test - namespace: default - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://common-hashicorp-vault.default.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/common-hashicorp-vault-normal.expected.yaml b/tests/common-hashicorp-vault-normal.expected.yaml deleted file mode 100644 index 4280e75d..00000000 --- a/tests/common-hashicorp-vault-normal.expected.yaml +++ /dev/null @@ -1,408 +0,0 @@ ---- -# Source: hashicorp-vault/charts/vault/templates/server-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm ---- -# Source: hashicorp-vault/charts/vault/templates/server-config-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: common-hashicorp-vault-config - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -data: - extraconfig-from-values.hcl: |- - disable_mlock = true - ui = true - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_cert_file = "/vault/userconfig/vault-secret/tls.crt" - tls_key_file = "/vault/userconfig/vault-secret/tls.key" - } - storage "file" { - path = "/vault/data" - } ---- -# Source: hashicorp-vault/charts/vault/templates/server-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: common-hashicorp-vault-server-binding - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:auth-delegator -subjects: -- kind: ServiceAccount - name: common-hashicorp-vault - namespace: pattern-namespace ---- -# Source: hashicorp-vault/charts/vault/templates/server-headless-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-internal - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - vault-internal: "true" - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret-internal -spec: - clusterIP: None - publishNotReadyAddresses: true - ports: - - name: "http" - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/server-service.yaml -# Service for Vault cluster -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm - annotations: - - - service.beta.openshift.io/serving-cert-secret-name: vault-secret -spec: - # We want the servers to become available even if they're not ready - # since this DNS is also used for join operations. - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - - name: https-internal - port: 8201 - targetPort: 8201 - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server ---- -# Source: hashicorp-vault/charts/vault/templates/ui-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: common-hashicorp-vault-ui - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault-ui - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - selector: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - publishNotReadyAddresses: true - ports: - - name: http - port: 8200 - targetPort: 8200 - type: ClusterIP ---- -# Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml -# StatefulSet to run the actual vault server cluster. -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - serviceName: common-hashicorp-vault-internal - podManagementPolicy: Parallel - replicas: 1 - updateStrategy: - type: OnDelete - selector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - template: - metadata: - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - component: server - spec: - - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/name: vault - app.kubernetes.io/instance: "common-hashicorp-vault" - component: server - topologyKey: kubernetes.io/hostname - - - - - terminationGracePeriodSeconds: 10 - serviceAccountName: common-hashicorp-vault - - volumes: - - - name: config - configMap: - name: common-hashicorp-vault-config - - - name: userconfig-vault-secret - secret: - secretName: vault-secret - defaultMode: 420 - - name: home - emptyDir: {} - containers: - - name: vault - - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - command: - - "/bin/sh" - - "-ec" - args: - - | - cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; - [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; - [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; - [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; - [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; - /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl - - env: - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: VAULT_K8S_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_K8S_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: VAULT_ADDR - value: "http://127.0.0.1:8200" - - name: VAULT_API_ADDR - value: "http://$(POD_IP):8200" - - name: SKIP_CHOWN - value: "true" - - name: SKIP_SETCAP - value: "true" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: VAULT_CLUSTER_ADDR - value: "https://$(HOSTNAME).common-hashicorp-vault-internal:8201" - - name: HOME - value: "/home/vault" - - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - - volumeMounts: - - - - - name: data - mountPath: /vault/data - - - - - name: config - mountPath: /vault/config - - - name: userconfig-vault-secret - readOnly: true - mountPath: /vault/userconfig/vault-secret - - name: home - mountPath: /home/vault - ports: - - containerPort: 8200 - name: http - - containerPort: 8201 - name: https-internal - - containerPort: 8202 - name: http-rep - readinessProbe: - # Check status; unsealed vault servers return 0 - # The exit code reflects the seal status: - # 0 - unsealed - # 1 - error - # 2 - sealed - exec: - command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] - failureThreshold: 2 - initialDelaySeconds: 5 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 3 - lifecycle: - # Vault container doesn't receive SIGTERM from Kubernetes - # and after the grace period ends, Kube sends SIGKILL. This - # causes issues with graceful shutdowns such as deregistering itself - # from Consul (zombie services). - preStop: - exec: - command: [ - "/bin/sh", "-c", - # Adding a sleep here to give the pod eviction a - # chance to propagate, so requests will not be made - # to this pod while it's terminating - "sleep 5 && kill -SIGTERM $(pidof vault)", - ] - - - volumeClaimTemplates: - - metadata: - name: data - - - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi ---- -# Source: hashicorp-vault/templates/vault-app.yaml -apiVersion: console.openshift.io/v1 -kind: ConsoleLink -metadata: - name: vault-link - namespace: vault -spec: - applicationMenu: - section: HashiCorp Vault - imageURL: data:image/png;base64,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 - href: 'https://vault-vault.apps.region.example.com' - location: ApplicationMenu - text: 'Vault' ---- -# Source: hashicorp-vault/charts/vault/templates/server-route.yaml -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: common-hashicorp-vault - namespace: pattern-namespace - labels: - helm.sh/chart: vault-0.27.0 - app.kubernetes.io/name: vault - app.kubernetes.io/instance: common-hashicorp-vault - app.kubernetes.io/managed-by: Helm -spec: - host: - to: - kind: Service - name: common-hashicorp-vault - weight: 100 - port: - targetPort: 8200 - tls: - termination: reencrypt ---- -# Source: hashicorp-vault/charts/vault/templates/tests/server-test.yaml -apiVersion: v1 -kind: Pod -metadata: - name: common-hashicorp-vault-server-test - namespace: pattern-namespace - annotations: - "helm.sh/hook": test -spec: - - containers: - - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi - imagePullPolicy: IfNotPresent - env: - - name: VAULT_ADDR - value: http://common-hashicorp-vault.pattern-namespace.svc:8200 - - - name: "VAULT_ADDR" - value: "https://vault.vault.svc.cluster.local:8200" - - name: "VAULT_CACERT" - value: "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt" - command: - - /bin/sh - - -c - - | - echo "Checking for sealed info in 'vault status' output" - ATTEMPTS=10 - n=0 - until [ "$n" -ge $ATTEMPTS ] - do - echo "Attempt" $n... - vault status -format yaml | grep -E '^sealed: (true|false)' && break - n=$((n+1)) - sleep 5 - done - if [ $n -ge $ATTEMPTS ]; then - echo "timed out looking for sealed info in 'vault status' output" - exit 1 - fi - - exit 0 - volumeMounts: - volumes: - restartPolicy: Never diff --git a/tests/common-install-industrial-edge-factory.expected.yaml b/tests/common-install-industrial-edge-factory.expected.yaml deleted file mode 100644 index b8ab08c5..00000000 --- a/tests/common-install-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Source: pattern-install/templates/argocd/namespace.yaml -# Pre-create so we can create our argo app for keeping subscriptions in sync -# Do it here so that we don't try to sync it in the future -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-gitops ---- -# Source: pattern-install/templates/argocd/application.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: common-install-hub - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: common-install-hub - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - # Track the progress of https://github.com/argoproj/argo-cd/pull/6280 - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: common-install - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.clusterVersion - value: "" - syncPolicy: - automated: {} ---- -# Source: pattern-install/templates/argocd/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: "" -spec: - channel: stable - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: common-install-hub,openshift-gitops diff --git a/tests/common-install-industrial-edge-hub.expected.yaml b/tests/common-install-industrial-edge-hub.expected.yaml deleted file mode 100644 index b8ab08c5..00000000 --- a/tests/common-install-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Source: pattern-install/templates/argocd/namespace.yaml -# Pre-create so we can create our argo app for keeping subscriptions in sync -# Do it here so that we don't try to sync it in the future -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-gitops ---- -# Source: pattern-install/templates/argocd/application.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: common-install-hub - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: common-install-hub - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - # Track the progress of https://github.com/argoproj/argo-cd/pull/6280 - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: common-install - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.clusterVersion - value: "" - syncPolicy: - automated: {} ---- -# Source: pattern-install/templates/argocd/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: "" -spec: - channel: stable - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: common-install-hub,openshift-gitops diff --git a/tests/common-install-medical-diagnosis-hub.expected.yaml b/tests/common-install-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index b8ab08c5..00000000 --- a/tests/common-install-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Source: pattern-install/templates/argocd/namespace.yaml -# Pre-create so we can create our argo app for keeping subscriptions in sync -# Do it here so that we don't try to sync it in the future -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-gitops ---- -# Source: pattern-install/templates/argocd/application.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: common-install-hub - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: common-install-hub - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - # Track the progress of https://github.com/argoproj/argo-cd/pull/6280 - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: common-install - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.clusterVersion - value: "" - syncPolicy: - automated: {} ---- -# Source: pattern-install/templates/argocd/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: "" -spec: - channel: stable - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: common-install-hub,openshift-gitops diff --git a/tests/common-install-naked.expected.yaml b/tests/common-install-naked.expected.yaml deleted file mode 100644 index 5c755fe6..00000000 --- a/tests/common-install-naked.expected.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Source: pattern-install/templates/argocd/namespace.yaml -# Pre-create so we can create our argo app for keeping subscriptions in sync -# Do it here so that we don't try to sync it in the future -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-gitops ---- -# Source: pattern-install/templates/argocd/application.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: common-install-default - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: common-install-default - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-default.yaml" - # Track the progress of https://github.com/argoproj/argo-cd/pull/6280 - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: common-install - - name: global.hubClusterDomain - value: - - name: global.clusterVersion - value: "" - syncPolicy: - automated: {} ---- -# Source: pattern-install/templates/argocd/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: "" -spec: - channel: stable - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: common-install-default,openshift-gitops diff --git a/tests/common-install-normal.expected.yaml b/tests/common-install-normal.expected.yaml deleted file mode 100644 index b8ab08c5..00000000 --- a/tests/common-install-normal.expected.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Source: pattern-install/templates/argocd/namespace.yaml -# Pre-create so we can create our argo app for keeping subscriptions in sync -# Do it here so that we don't try to sync it in the future -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-gitops ---- -# Source: pattern-install/templates/argocd/application.yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: common-install-hub - namespace: openshift-gitops - finalizers: - - resources-finalizer.argocd.argoproj.io/foreground -spec: - destination: - name: in-cluster - namespace: common-install-hub - project: default - source: - repoURL: https://github.com/pattern-clone/mypattern - targetRevision: main - path: common/clustergroup - helm: - ignoreMissingValueFiles: true - valueFiles: - - "/values-global.yaml" - - "/values-hub.yaml" - # Track the progress of https://github.com/argoproj/argo-cd/pull/6280 - parameters: - - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL - - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: common-install - - name: global.hubClusterDomain - value: apps.hub.example.com - - name: global.clusterVersion - value: "" - syncPolicy: - automated: {} ---- -# Source: pattern-install/templates/argocd/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-operators - labels: - operators.coreos.com/openshift-gitops-operator.openshift-operators: "" -spec: - channel: stable - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: common-install-hub,openshift-gitops diff --git a/tests/common-letsencrypt-industrial-edge-factory.expected.yaml b/tests/common-letsencrypt-industrial-edge-factory.expected.yaml deleted file mode 100644 index b5aded2f..00000000 --- a/tests/common-letsencrypt-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.region.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.region.example.com' - usages: - - server auth - dnsNames: - - api.region.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.region.example.com' - usages: - - server auth - dnsNames: - - '*.apps.region.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/common-letsencrypt-industrial-edge-hub.expected.yaml b/tests/common-letsencrypt-industrial-edge-hub.expected.yaml deleted file mode 100644 index b5aded2f..00000000 --- a/tests/common-letsencrypt-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.region.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.region.example.com' - usages: - - server auth - dnsNames: - - api.region.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.region.example.com' - usages: - - server auth - dnsNames: - - '*.apps.region.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/common-letsencrypt-medical-diagnosis-hub.expected.yaml b/tests/common-letsencrypt-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index b5aded2f..00000000 --- a/tests/common-letsencrypt-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.region.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.region.example.com' - usages: - - server auth - dnsNames: - - api.region.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.region.example.com' - usages: - - server auth - dnsNames: - - '*.apps.region.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/common-letsencrypt-naked.expected.yaml b/tests/common-letsencrypt-naked.expected.yaml deleted file mode 100644 index 73aa94a4..00000000 --- a/tests/common-letsencrypt-naked.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.example.com' - usages: - - server auth - dnsNames: - - api.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.example.com' - usages: - - server auth - dnsNames: - - '*.apps.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/common-letsencrypt-normal.expected.yaml b/tests/common-letsencrypt-normal.expected.yaml deleted file mode 100644 index b5aded2f..00000000 --- a/tests/common-letsencrypt-normal.expected.yaml +++ /dev/null @@ -1,202 +0,0 @@ ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager-operator -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cert-manager -spec: ---- -# Source: letsencrypt/templates/namespaces.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: letsencrypt -spec: ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: config.openshift.io/v1 -kind: APIServer -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - servingCerts: - namedCertificates: - - names: - - api.region.example.com - servingCertificate: - name: api-validated-patterns-letsencrypt-cert ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: argoproj.io/v1alpha1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - server: - route: - enabled: true - tls: - termination: reencrypt ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operator.openshift.io/v1alpha1 -kind: CertManager -metadata: - name: cluster - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - managementState: "Managed" - unsupportedConfigOverrides: - # Here's an example to supply custom DNS settings. - controller: - args: - - "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53" - - "--dns01-recursive-nameservers-only" ---- -# Source: letsencrypt/templates/api-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-validated-patterns-cert - namespace: openshift-config - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: api-validated-patterns-letsencrypt-cert - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: 'api.region.example.com' - usages: - - server auth - dnsNames: - - api.region.example.com - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/wildcard-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: lets-encrypt-certs - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - secretName: lets-encrypt-wildcart-cert-tls - duration: 168h0m0s - renewBefore: 28h0m0s - commonName: '*.apps.region.example.com' - usages: - - server auth - dnsNames: - - '*.apps.region.example.com' - issuerRef: - name: validated-patterns-issuer - kind: ClusterIssuer - subject: - organizations: - - hybrid-cloud-patterns.io ---- -# Source: letsencrypt/templates/issuer.yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: validated-patterns-issuer - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: test@example.com - privateKeySecretRef: - name: validated-patterns-issuer-account-key - solvers: - - selector: {} - dns01: - route53: - region: eu-central-1 - accessKeyIDSecretRef: - name: cert-manager-dns-credentials - key: aws_access_key_id - secretAccessKeySecretRef: - name: cert-manager-dns-credentials - key: aws_secret_access_key ---- -# Source: letsencrypt/templates/credentials-request.yaml -apiVersion: cloudcredential.openshift.io/v1 -kind: CredentialsRequest -metadata: - name: letsencrypt-cert-manager-dns - namespace: openshift-cloud-credential-operator - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - providerSpec: - apiVersion: cloudcredential.openshift.io/v1 - kind: AWSProviderSpec - statementEntries: - - action: - - 'route53:ChangeResourceRecordSets' - - 'route53:GetChange' - - 'route53:ListHostedZonesByName' - - 'route53:ListHostedZones' - effect: Allow - resource: '*' - secretRef: - name: cert-manager-dns-credentials - namespace: cert-manager ---- -# Source: letsencrypt/templates/default-routes.yaml -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator - annotations: - argocd.argoproj.io/sync-options: ServerSideApply=true, Validate=false, SkipDryRunOnMissingResource=true -spec: - routeAdmission: - wildcardPolicy: WildcardsAllowed - defaultCertificate: - name: lets-encrypt-wildcart-cert-tls -# Patch the cluster-wide argocd instance so it uses the ingress tls cert ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: cert-manager-operator - namespace: cert-manager-operator -spec: - targetNamespaces: - - cert-manager-operator ---- -# Source: letsencrypt/templates/cert-manager-installation.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-cert-manager-operator - namespace: cert-manager-operator -spec: - channel: "stable-v1" - installPlanApproval: Automatic - name: openshift-cert-manager-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tests/common-operator-install-industrial-edge-factory.expected.yaml b/tests/common-operator-install-industrial-edge-factory.expected.yaml deleted file mode 100644 index f1950e9e..00000000 --- a/tests/common-operator-install-industrial-edge-factory.expected.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: common-operator-install - namespace: openshift-operators -spec: - clusterGroupName: hub - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.11 - operatorSource: redhat-operators - multiSourceConfig: - enabled: true ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace diff --git a/tests/common-operator-install-industrial-edge-hub.expected.yaml b/tests/common-operator-install-industrial-edge-hub.expected.yaml deleted file mode 100644 index f1950e9e..00000000 --- a/tests/common-operator-install-industrial-edge-hub.expected.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: common-operator-install - namespace: openshift-operators -spec: - clusterGroupName: hub - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.11 - operatorSource: redhat-operators - multiSourceConfig: - enabled: true ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace diff --git a/tests/common-operator-install-medical-diagnosis-hub.expected.yaml b/tests/common-operator-install-medical-diagnosis-hub.expected.yaml deleted file mode 100644 index f1950e9e..00000000 --- a/tests/common-operator-install-medical-diagnosis-hub.expected.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: common-operator-install - namespace: openshift-operators -spec: - clusterGroupName: hub - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.11 - operatorSource: redhat-operators - multiSourceConfig: - enabled: true ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace diff --git a/tests/common-operator-install-naked.expected.yaml b/tests/common-operator-install-naked.expected.yaml deleted file mode 100644 index 22145c15..00000000 --- a/tests/common-operator-install-naked.expected.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: common-operator-install - namespace: openshift-operators -spec: - clusterGroupName: default - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.11 - operatorSource: redhat-operators - multiSourceConfig: - enabled: false ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace diff --git a/tests/common-operator-install-normal.expected.yaml b/tests/common-operator-install-normal.expected.yaml deleted file mode 100644 index f1950e9e..00000000 --- a/tests/common-operator-install-normal.expected.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -# Source: pattern-install/templates/pattern-operator-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: patterns-operator-config - namespace: openshift-operators -data: - gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 - - # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace - # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan - # gitops.ManualSync: GitOpsDefaultManualSync - # gitops.name: GitOpsDefaultPackageName ---- -# Source: pattern-install/templates/pattern.yaml -apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 -kind: Pattern -metadata: - name: common-operator-install - namespace: openshift-operators -spec: - clusterGroupName: hub - gitSpec: - targetRepo: https://github.com/pattern-clone/mypattern - targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.11 - operatorSource: redhat-operators - multiSourceConfig: - enabled: true ---- -# Source: pattern-install/templates/subscription.yaml -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: patterns-operator - namespace: openshift-operators - labels: - operators.coreos.com/patterns-operator.openshift-operators: "" -spec: - channel: fast - installPlanApproval: Automatic - name: patterns-operator - source: community-operators - sourceNamespace: openshift-marketplace From 98744fb1316eb40135767af2a8e0ea7154851c72 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sun, 9 Feb 2025 18:52:05 +0100 Subject: [PATCH 209/222] Add a CI job for pattern.sh --- .github/workflows/pattern-sh-ci.yml | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/pattern-sh-ci.yml diff --git a/.github/workflows/pattern-sh-ci.yml b/.github/workflows/pattern-sh-ci.yml new file mode 100644 index 00000000..9aa4cf4e --- /dev/null +++ b/.github/workflows/pattern-sh-ci.yml @@ -0,0 +1,41 @@ +name: Run Bash Script on Multiple Distributions + +on: + push: + branches: + - main + pull_request: + +jobs: + run-script: + name: Run Bash Script + strategy: + matrix: + # Fedora is not an option yet + os: [ubuntu-latest, ubuntu-22.04] + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Install Podman on Ubuntu + if: contains(matrix.os, 'ubuntu') + run: | + sudo apt-get update + sudo apt-get install -y podman + + # Currently we do not do MacOSX as it is not free, maybe in the future + # - name: Install Podman on macOS + # if: contains(matrix.os, 'macos') + # run: | + # brew install podman + # podman machine init + # podman machine start + + - name: Verify Podman Installation + run: podman --version + + - name: Run pattern.sh script + run: | + ./scripts/pattern-util.sh make validate-origin From 7c950f678f1dd71acffa80b69dfba212a696eb04 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Feb 2025 09:15:27 +0100 Subject: [PATCH 210/222] Allow TARGET_BRANCH to be overridden --- .github/workflows/pattern-sh-ci.yml | 1 + Makefile | 2 +- scripts/pattern-util.sh | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pattern-sh-ci.yml b/.github/workflows/pattern-sh-ci.yml index 9aa4cf4e..92eadfd5 100644 --- a/.github/workflows/pattern-sh-ci.yml +++ b/.github/workflows/pattern-sh-ci.yml @@ -38,4 +38,5 @@ jobs: - name: Run pattern.sh script run: | + export TARGET_BRANCH=main ./scripts/pattern-util.sh make validate-origin diff --git a/Makefile b/Makefile index fc10236e..4e977e10 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ TARGET_ORIGIN ?= origin # This is because we expect to use tokens for repo authentication as opposed to SSH keys TARGET_REPO=$(shell git ls-remote --get-url --symref $(TARGET_ORIGIN) | sed -e 's/.*URL:[[:space:]]*//' -e 's%^git@%%' -e 's%^https://%%' -e 's%:%/%' -e 's%^%https://%') # git branch --show-current is also available as of git 2.22, but we will use this for compatibility -TARGET_BRANCH=$(shell git rev-parse --abbrev-ref HEAD) +TARGET_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) UUID_FILE ?= ~/.config/validated-patterns/pattern-uuid UUID_HELM_OPTS ?= diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index 27b30229..8258d469 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -88,6 +88,7 @@ podman run -it --rm --pull=newer \ -e EXTRA_PLAYBOOK_OPTS \ -e TARGET_ORIGIN \ -e TARGET_SITE \ + -e TARGET_BRANCH \ -e NAME \ -e TOKEN_SECRET \ -e TOKEN_NAMESPACE \ From 46af2026b3c8221b143580826bc6c3f800c449f0 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Feb 2025 09:17:50 +0100 Subject: [PATCH 211/222] Restrict GH actions only to certain files --- .github/workflows/pattern-sh-ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/pattern-sh-ci.yml b/.github/workflows/pattern-sh-ci.yml index 92eadfd5..ed0e6a07 100644 --- a/.github/workflows/pattern-sh-ci.yml +++ b/.github/workflows/pattern-sh-ci.yml @@ -2,9 +2,15 @@ name: Run Bash Script on Multiple Distributions on: push: + paths: + - "scripts/**" + - "Makefile" branches: - main pull_request: + paths: + - "scripts/**" + - "Makefile" jobs: run-script: From 2cdaac159b0c793e1058d88bb854136a1a259172 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Feb 2025 09:39:17 +0100 Subject: [PATCH 212/222] Drop some unused workflows --- .github/workflows/ansible-lint.yml | 17 ------- .github/workflows/jsonschema.yaml | 72 ------------------------------ .github/workflows/linter.yml | 65 --------------------------- 3 files changed, 154 deletions(-) delete mode 100644 .github/workflows/ansible-lint.yml delete mode 100644 .github/workflows/jsonschema.yaml delete mode 100644 .github/workflows/linter.yml diff --git a/.github/workflows/ansible-lint.yml b/.github/workflows/ansible-lint.yml deleted file mode 100644 index c2b2981b..00000000 --- a/.github/workflows/ansible-lint.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Ansible Lint # feel free to pick your own name - -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - # Important: This sets up your GITHUB_WORKSPACE environment variable - - uses: actions/checkout@v4 - - - name: Lint Ansible Playbook - uses: ansible/ansible-lint-action@v6 - # Let's point it to the path - with: - path: "ansible/" diff --git a/.github/workflows/jsonschema.yaml b/.github/workflows/jsonschema.yaml deleted file mode 100644 index 75a161ae..00000000 --- a/.github/workflows/jsonschema.yaml +++ /dev/null @@ -1,72 +0,0 @@ ---- -name: Verify json schema - -# -# Documentation: -# https://help.github.com/en/articles/workflow-syntax-for-github-actions -# - -############################# -# Start the job on all push # -############################# -on: [push, pull_request] - -############### -# Set the Job # -############### -jobs: - jsonschema_tests: - # Name the Job - name: Json Schema tests - strategy: - matrix: - python-version: [3.11] - # Set the agent to run on - runs-on: ubuntu-latest - - ################## - # Load all steps # - ################## - steps: - ########################## - # Checkout the code base # - ########################## - - name: Checkout Code - uses: actions/checkout@v4 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install check-jsonschema - - - name: Install yq - uses: chrisdickinson/setup-yq@latest - with: - yq-version: v4.30.7 - - - name: Verify secrets json schema against templates - run: | - # check-jsonschema needs .yaml as an extension - cp ./values-secret.yaml.template ./values-secret.yaml - check-jsonschema --schemafile ./common/ansible/roles/vault_utils/values-secrets.v2.schema.json values-secret.yaml - rm -f ./values-secret.yaml - - - name: Verify ClusterGroup values.schema.json against values-*yaml files - run: | - set -e; for i in values-hub.yaml values-group-one.yaml; do - echo "$i" - # disable shellcheck of single quotes in yq - # shellcheck disable=2016 - yq eval-all '. as $item ireduce ({}; . * $item )' values-global.yaml "$i" > tmp.yaml - check-jsonschema --schemafile ./common/clustergroup/values.schema.json tmp.yaml - rm -f tmp.yaml - done - diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml deleted file mode 100644 index c5b6aede..00000000 --- a/.github/workflows/linter.yml +++ /dev/null @@ -1,65 +0,0 @@ ---- -name: Unit tests - -# -# Documentation: -# https://help.github.com/en/articles/workflow-syntax-for-github-actions -# - -############################# -# Start the job on all push # -############################# -on: [push, pull_request] - -############### -# Set the Job # -############### -jobs: - build: - # Name the Job - name: Unit Test Code Base - # Set the agent to run on - runs-on: ubuntu-latest - - ################## - # Load all steps # - ################## - steps: - ########################## - # Checkout the code base # - ########################## - - name: Checkout Code - uses: actions/checkout@v4 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - name: Setup helm - uses: azure/setup-helm@v4 - with: - version: 'v3.13.2' - id: install - - ################################ - # Run Linter against code base # - ################################ - # - name: Lint Code Base - # uses: github/super-linter@v4 - # env: - # VALIDATE_ALL_CODEBASE: false - # DEFAULT_BRANCH: main - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Run make test - run: | - make test - - - name: Run make helmlint - run: | - make helmlint - - # Disable kubeconform for the time being - # - name: Run make helm kubeconform - # run: | - # curl -L -O https://github.com/yannh/kubeconform/releases/download/v0.4.13/kubeconform-linux-amd64.tar.gz - # tar xf kubeconform-linux-amd64.tar.gz - # sudo mv -v kubeconform /usr/local/bin - # make kubeconform From f13999d58271f829be272cd757ae226e7328ddc9 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Feb 2025 09:55:27 +0100 Subject: [PATCH 213/222] Fix super-linter complaints --- .github/linters/.markdown-lint.yml | 5 ++-- GPU_provisioning.md | 11 ++++++-- README.md | 21 ++++++---------- TESTPLAN.md | 24 ++++++++---------- tests/interop/test_subscription_status_hub.py | 8 +++--- tests/interop/test_validate_gpu_nodes.py | 13 +++++----- .../test_validate_hub_site_components.py | 25 +++++++++---------- 7 files changed, 52 insertions(+), 55 deletions(-) diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml index a0bc47d1..8eef43e9 100644 --- a/.github/linters/.markdown-lint.yml +++ b/.github/linters/.markdown-lint.yml @@ -2,5 +2,6 @@ "default": true, "MD003": false, "MD013": false, - "MD033": false -} \ No newline at end of file + "MD033": false, + "MD036": false +} diff --git a/GPU_provisioning.md b/GPU_provisioning.md index 930e5368..aa5427d3 100644 --- a/GPU_provisioning.md +++ b/GPU_provisioning.md @@ -43,11 +43,18 @@ spec: Use `kubectl` or `oc` command line to create new machineset `oc apply -f gpu_machineset.yaml` -Depending on type of EC2 instance creation of the new machines make take some time. Please note that all nodes with GPU will have labels(`node-role.kubernetes.io/odh-notebook`in our case) and taints (`odh-notebook `) that we have specified in machineset applied automatically +Depending on type of EC2 instance creation of the new machines make take some +time. Please note that all nodes with GPU will have +labels(`node-role.kubernetes.io/odh-notebook` in our case) and taints +(`odh-notebook`) that we have specified in machineset applied automatically ## Install Node Feature Operator -From OperatorHub install `Node Feature Discovery Operator` , accepting defaults . Once Operator has been installed , create `NodeFeatureDiscovery`instance . Use default entries unless you something specific is needed . Node Feature Discovery Operator will add labels to nodes based on available hardware resources +From OperatorHub install `Node Feature Discovery Operator` , accepting +defaults. Once Operator has been installed, create +`NodeFeatureDiscovery`instance. Use default entries unless you something +specific is needed. Node Feature Discovery Operator will add labels to nodes +based on available hardware resources. ![Diagram](images/node-feature-discovery.png) diff --git a/README.md b/README.md index fde70ea6..791f54e7 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ OpenShift to generate project proposals for specific Red Hat products. - Podman - Red Hat Openshift cluster running in AWS. Supported regions are : us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 sa-east-1 eu-west-1 eu-west-2 eu-west-3 eu-central-1 eu-north-1 ap-northeast-1 ap-northeast-2 ap-northeast-3 ap-southeast-1 ap-southeast-2 ap-south-1. - GPU Node to run Hugging Face Text Generation Inference server on Red Hat OpenShift cluster. -- Create a fork of the [rag-llm-gitops](https://github.com/validatedpatterns/rag-llm-gitops.git) git repository. +- Create a fork of the [rag-llm-gitops](https://github.com/validatedpatterns/rag-llm-gitops.git) Git repository. ## Demo Description & Architecture @@ -33,52 +33,45 @@ The application generates a project proposal for a Red Hat product. - Multiple LLM providers (OpenAI, Hugging Face, NVIDIA). - Vector Database, such as EDB Postgres for Kubernetes or Redis, to store embeddings of Red Hat product documentation. - Monitoring dashboard to provide key metrics such as ratings. -- GitOps setup to deploy e2e demo (frontend / vector database / served models). +- GitOps setup to deploy end-to-end demo (frontend / vector database / served models). ![Overview](https://gitlab.com/osspa/portfolio-architecture-examples/-/raw/main/images/intro-marketectures/rag-demo-vp-marketing-slide.png) _Figure 1. Overview of the validated pattern for RAG Demo with Red Hat OpenShift_ - ![Logical](https://gitlab.com/osspa/portfolio-architecture-examples/-/raw/main/images/logical-diagrams/rag-demo-vp-ld.png) _Figure 2. Logical diagram of the RAG Demo with Red Hat OpenShift._ - #### RAG Demo Workflow ![Overview of workflow](https://gitlab.com/osspa/portfolio-architecture-examples/-/raw/main/images/schematic-diagrams/rag-demo-vp-sd.png) _Figure 3. Schematic diagram for workflow of RAG demo with Red Hat OpenShift._ - #### RAG Data Ingestion ![ingestion](https://gitlab.com/osspa/portfolio-architecture-examples/-/raw/main/images/schematic-diagrams/rag-demo-vp-ingress-sd.png) _Figure 4. Schematic diagram for Ingestion of data for RAG._ - #### RAG Augmented Query - ![query](https://gitlab.com/osspa/portfolio-architecture-examples/-/raw/main/images/schematic-diagrams/rag-demo-vp-query-sd.png) _Figure 5. Schematic diagram for RAG demo augmented query._ - In Figure 5, we can see RAG augmented query. [IBM Granite 3.1-8B-Instruct](https://huggingface.co/ibm-granite/granite-3.1-8b-instruct) model is used for language processing, LangChain to integrate different tools of the LLM-based application together and to process the PDF files and web pages, vector database provider such as EDB Postgres for Kubernetes or Redis, is used to store vectors, and [Red Hat OpenShift AI](https://www.redhat.com/en/technologies/cloud-computing/openshift/openshift-ai) to serve the [IBM Granite 3.1-8B-Instruct](https://huggingface.co/ibm-granite/granite-3.1-8b-instruct) model, Gradio is used for user interface and object storage to store language model and other datasets. Solution components are deployed as microservices in the Red Hat OpenShift cluster. - #### Download diagrams + View and download all of the diagrams above in our open source tooling site. [Open Diagrams](https://www.redhat.com/architect/portfolio/tool/index.html?#gitlab.com/osspa/portfolio-architecture-examples/-/raw/main/diagrams/rag-demo-vp.drawio) - ![Diagram](images/diagram.png) _Figure 6. Proposed demo architecture with OpenShift AI_ @@ -93,11 +86,11 @@ _Figure 6. Proposed demo architecture with OpenShift AI_ ## Deploying the demo -To run the demo, ensure the Podman is running on your machine.Fork the [rag-llm-gitops](https://github.com/validatedpatterns/rag-llm-gitops) repo into your organization +To run the demo, ensure the Podman is running on your machine.Fork the [rag-llm-gitops](https://github.com/validatedpatterns/rag-llm-gitops) repository into your organization ### Login to OpenShift cluster -Replace the token and the api server url in the command below to login to the OpenShift cluster. +Replace the token and the API server URL in the command below to login to the OpenShift cluster. ```sh oc login --token= --server= # login to Openshift cluster @@ -112,7 +105,7 @@ cd rag-llm-gitops ### Configuring model -This pattern deploys [IBM Granite 3.1-8B-Instruct](https://huggingface.co/ibm-granite/granite-3.1-8b-instruct) out of box. Run the following command to configure vault with the model Id. +This pattern deploys [IBM Granite 3.1-8B-Instruct](https://huggingface.co/ibm-granite/granite-3.1-8b-instruct) out of box. Run the following command to configure vault with the model ID. ```sh # Copy values-secret.yaml.template to ~/values-secret-rag-llm-gitops.yaml. @@ -254,10 +247,10 @@ By default, Grafana application is deployed in `llm-monitoring` namespace.To lau ![Routes](images/monitoring.png) ## Test Plan + GOTO: [Test Plan](./TESTPLAN.md) ## Licenses EDB Postgres for Kubernetes is distributed under the EDB Limited Usage License Agreement, available at [enterprisedb.com/limited-use-license](https://www.enterprisedb.com/limited-use-license). - diff --git a/TESTPLAN.md b/TESTPLAN.md index 7d09b9be..60908a3b 100644 --- a/TESTPLAN.md +++ b/TESTPLAN.md @@ -1,10 +1,11 @@ -# Test Cases for E2E Demo. +# Test Cases for End-to-End Demo - [Provisioning of GPU Node](https://github.com/validatedpatterns-sandbox/rag-llm-gitops/blob/main/GPU_provisioning.md) - MachineSet is created. - - Name of the machine set -gpu-. This should not be a hard requirement though. + - Name of the machine set -gpu-. This should not be a hard requirement though. - Machine set has taint section + ```yaml taints: - effect: NoSchedule @@ -13,6 +14,7 @@ ``` - MachineSet has a label + ```yaml metadata: labels: @@ -20,6 +22,7 @@ ``` - MachineSet instance type + ```yaml providerSpec: value: @@ -40,16 +43,16 @@ - Click on the Node Feature Discovery Operator. Under NodeFeatureDiscovery an instance should be created. Status should be Available. ![nfd instance](https://validatedpatterns.io/images/rag-llm-gitops/ragllm-nfd-instance.png) - - Verify NVIDIA GPU Operator is installed. - NVIDIA GPU Operator is installed - + ![nvidia operator](https://validatedpatterns.io/images/rag-llm-gitops/ragllm-nvidia-operator.png) - Click on the NVIDIA GPU Operator and click on ClusterPolicy. A gpu-cluster-policy should exist - ![nvidia clusterpolicies](https://validatedpatterns.io/images/rag-llm-gitops/ragllm-nvidia-clusterpolicies.png) + ![nvidia clusterpolicies](https://validatedpatterns.io/images/rag-llm-gitops/ragllm-nvidia-clusterpolicies.png) - Click on the gpu-cluster-policy and click on the YAML tab. The YAML should contain the tolerations + ```yaml tolerations: - effect: NoSchedule @@ -59,13 +62,13 @@ - Application provisioned correctly. - Click on the rag-llm namespace - + - By Default, EDB Operator will be deployed, which will deploy PGVECTOR vector database, 6 pods should be running ![ragllm pgvector pods](https://validatedpatterns.io/images/rag-llm-gitops/rag-llm-pgvector.png) - If the global.db.type is set to REDIS in the values-global.yaml, four pods should be running ![ragllm pods](https://validatedpatterns.io/images/rag-llm-gitops/rag-llm.png) - + - Click on Networking → Routes from the left Navigation panel. An llm-ui route should exist ![llm-ui route](https://validatedpatterns.io/images/rag-llm-gitops/ragllm-application_route.png) @@ -88,10 +91,5 @@ - Enter the Grafana admin credentials. - Ratings are displayed for each model - Grafana Dashboard is displayed - - ![llm-ui grafana](https://validatedpatterns.io/images/rag-llm-gitops/ragllm-grafana.png) - - - - + ![llm-ui grafana](https://validatedpatterns.io/images/rag-llm-gitops/ragllm-grafana.png) diff --git a/tests/interop/test_subscription_status_hub.py b/tests/interop/test_subscription_status_hub.py index cc3306c9..eba587fa 100644 --- a/tests/interop/test_subscription_status_hub.py +++ b/tests/interop/test_subscription_status_hub.py @@ -13,10 +13,10 @@ def test_subscription_status_hub(openshift_dyn_client): # These are the operator subscriptions and their associated namespaces expected_subs = { "openshift-gitops-operator": ["openshift-operators"], - "prometheus": ["llm-monitoring"], - "grafana-operator": ["llm-monitoring"], - "nfd": ["openshift-nfd"], - "gpu-operator-certified": ["nvidia-gpu-operator"], + "prometheus": ["llm-monitoring"], + "grafana-operator": ["llm-monitoring"], + "nfd": ["openshift-nfd"], + "gpu-operator-certified": ["nvidia-gpu-operator"], } err_msg = subscription.subscription_status( diff --git a/tests/interop/test_validate_gpu_nodes.py b/tests/interop/test_validate_gpu_nodes.py index 6b591ba3..a03f9fb8 100644 --- a/tests/interop/test_validate_gpu_nodes.py +++ b/tests/interop/test_validate_gpu_nodes.py @@ -1,14 +1,13 @@ +import logging import os import re import subprocess + import pytest -import logging -import yaml from ocp_resources.machine_set import MachineSet from ocp_resources.node import Node -from ocp_resources.pod import Pod + from . import __loggername__ -from openshift.dynamic.exceptions import NotFoundError logger = logging.getLogger(__loggername__) @@ -34,7 +33,7 @@ def test_validate_gpu_nodes(openshift_dyn_client): break err_msg = "GPU machineset not found" - if found == True: + if found: logger.info( f"PASS: Found GPU machineset: {gpu_machineset.instance.metadata.name}" ) @@ -129,7 +128,7 @@ def test_validate_gpu_node_role_labels_pods(openshift_dyn_client): # logger.info(node_count) if len(gpu_nodes) == 3: - logger.info(f"PASS: Found 'worker' and 'odh-notebook' GPU node-role labels") + logger.info("PASS: Found 'worker' and 'odh-notebook' GPU node-role labels") else: err_msg = "Could not find 'worker' and 'odh-notebook' GPU node-role label" logger.error(f"FAIL: {err_msg}") @@ -171,4 +170,4 @@ def test_validate_gpu_node_role_labels_pods(openshift_dyn_client): logger.error(f"FAIL: {err_msg}") assert False, err_msg else: - logger.info(f"PASS: Found the expected pod count for GPU nodes") + logger.info("PASS: Found the expected pod count for GPU nodes") diff --git a/tests/interop/test_validate_hub_site_components.py b/tests/interop/test_validate_hub_site_components.py index 5699c632..3519b673 100644 --- a/tests/interop/test_validate_hub_site_components.py +++ b/tests/interop/test_validate_hub_site_components.py @@ -5,8 +5,8 @@ import pytest from ocp_resources.pod import Pod from ocp_resources.route import Route -from openshift.dynamic.exceptions import NotFoundError from ocp_resources.storage_class import StorageClass +from openshift.dynamic.exceptions import NotFoundError from validatedpatterns_tests.interop import application, components from . import __loggername__ @@ -44,10 +44,7 @@ def test_validate_hub_site_reachable(kube_config, openshift_dyn_client): @pytest.mark.check_pod_status_hub def test_check_pod_status(openshift_dyn_client): logger.info("Checking pod status") - projects = [ - "nvidia-gpu-operator", - "rag-llm" - ] + projects = ["nvidia-gpu-operator", "rag-llm"] err_msg = components.check_pod_status(openshift_dyn_client, projects) if err_msg: logger.error(f"FAIL: {err_msg}") @@ -59,9 +56,7 @@ def test_check_pod_status(openshift_dyn_client): @pytest.mark.check_pod_count_hub def test_check_pod_count_hub(openshift_dyn_client): logger.info("Checking pod count") - projects = { - "rag-llm": 4 - } + projects = {"rag-llm": 4} failed = [] for key in projects.keys(): @@ -74,7 +69,8 @@ def test_check_pod_count_hub(openshift_dyn_client): count += 1 logger.info(f"Found {count} pods") - if count < projects[key]: failed.append(key) + if count < projects[key]: + failed.append(key) if len(failed) > 0: err_msg = f"Failed to find the expected pod count for: {failed}" @@ -121,7 +117,8 @@ def test_validate_nodefeaturediscovery(): logger.info("Check for nodefeaturediscovery instance") cmd_out = subprocess.run( - [oc, "get", "NodeFeatureDiscovery", "-n", namespace, name, "--no-headers"], capture_output=True + [oc, "get", "NodeFeatureDiscovery", "-n", namespace, name, "--no-headers"], + capture_output=True, ) if cmd_out.stdout: logger.info(cmd_out.stdout.decode("utf-8")) @@ -133,7 +130,9 @@ def test_validate_nodefeaturediscovery(): @pytest.mark.validate_gpu_clusterpolicy def test_validate_gpu_clusterpolicy(): name = "rag-llm-gpu-cluster-policy" - tolerations = '"tolerations":[{"effect":"NoSchedule","key":"odh-notebook","value":"true"}]' + tolerations = ( + '"tolerations":[{"effect":"NoSchedule","key":"odh-notebook","value":"true"}]' + ) logger.info("Check for GPU clusterpolicy") cmd_out = subprocess.run( @@ -141,11 +140,11 @@ def test_validate_gpu_clusterpolicy(): ) if cmd_out.stdout: logger.info(cmd_out.stdout.decode("utf-8")) - + if tolerations in cmd_out.stdout.decode("utf-8"): logger.info("PASS: Found GPU clusterpolicy and tolerations") else: - err_msg =f"FAIL: Expected tolerations not found" + err_msg = "FAIL: Expected tolerations not found" logger.error(f"FAIL: {err_msg}") assert False, err_msg else: From 9b986b068bf3bb45368c833f0c7bbe5a1f332646 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Feb 2025 09:56:06 +0100 Subject: [PATCH 214/222] Switch to newer super-linter --- .github/workflows/superlinter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 541bf7b8..8795d50f 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -21,7 +21,7 @@ jobs: # Run Linter against code base # ################################ - name: Lint Code Base - uses: github/super-linter/slim@v6 + uses: super-linter/super-linter/slim@v7 env: VALIDATE_ALL_CODEBASE: true DEFAULT_BRANCH: main From 7806437af71d4d21f446c0cf032ced9ddcefa2f6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Feb 2025 10:04:13 +0100 Subject: [PATCH 215/222] Disable some checks in super-linter --- .github/workflows/superlinter.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 8795d50f..39c6fcc8 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -32,6 +32,10 @@ jobs: VALIDATE_KUBERNETES_KUBECONFORM: false VALIDATE_YAML: false VALIDATE_ANSIBLE: false + VALIDATE_PYTHON_PYLINT: false + VALIDATE_MARKDOWN_PRETTIER: false + VALIDATE_SHELL_SHFMT: false + VALIDATE_YAML_PRETTIER: false # VALIDATE_DOCKERFILE_HADOLINT: false # VALIDATE_MARKDOWN: false # VALIDATE_NATURAL_LANGUAGE: false From b029ad5599829dbfe3bb5050460f6b25a2f7cb43 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Feb 2025 10:14:04 +0100 Subject: [PATCH 216/222] Disable CHECKOV --- .github/workflows/superlinter.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 39c6fcc8..b4990556 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -28,6 +28,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # These are the validation we disable atm VALIDATE_BASH: false + VALIDATE_CHECKOV: false VALIDATE_JSCPD: false VALIDATE_KUBERNETES_KUBECONFORM: false VALIDATE_YAML: false From 8a9a7eb50e2d133e41186b242e182a497560ea85 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 11 Feb 2025 17:51:38 +0100 Subject: [PATCH 217/222] Drop version from GrafanaDataSource There is no such field in the operator's CRD and it causes argo to be outofsync. $ grep -B5 -ir version: config/crd/bases/grafana.integreatly.org_grafanadatasources.yaml --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.3 -- name: v1beta1 schema: openAPIV3Schema: description: GrafanaDatasource is the Schema for the grafanadatasources API properties: apiVersion: -- description: plugins items: properties: name: type: string version: $ git lg --grep version config/crd/bases/grafana.integreatly.org_grafanadatasources.yaml $ --- .../kustomize/base/grafana/prometheus-datasource.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/charts/all/llm-monitoring/kustomize/base/grafana/prometheus-datasource.yaml b/charts/all/llm-monitoring/kustomize/base/grafana/prometheus-datasource.yaml index 19902eee..c075c07b 100644 --- a/charts/all/llm-monitoring/kustomize/base/grafana/prometheus-datasource.yaml +++ b/charts/all/llm-monitoring/kustomize/base/grafana/prometheus-datasource.yaml @@ -14,7 +14,6 @@ spec: jsonData: timeInterval: 5s isDefault: true - version: 1 type: prometheus instanceSelector: matchLabels: From 1fdba195d3e44d9e55bf76e869903f39cb52a3d0 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 11 Feb 2025 18:52:46 +0100 Subject: [PATCH 218/222] Add help line for create-gpu-machineset --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0a6f57d6..61426ed5 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ install: operator-deploy post-install ## installs the pattern and loads the secr @echo "Installed" .PHONY: create-gpu-machineset -create-gpu-machineset: +create-gpu-machineset: ## Creates a gpu machineset ansible-playbook ansible/playbooks/create-gpu-machine-set.yaml .PHONY: post-install From 39882c74be9689498d4b945f670a1efc5b32247c Mon Sep 17 00:00:00 2001 From: Drew Minnear Date: Tue, 25 Feb 2025 13:27:12 -0500 Subject: [PATCH 219/222] propagate the env var EXTRA_PLAYBOOK_OPTS to our ansible-playbook commands Currently, we pass the env var EXTRA_PLAYBOOK_OPTS into our utility container when running the `pattern-util.sh` script, however, we do not use it anywhere. This commit adds propagation of the env var to the `ansible-playbook` commands which could make use of it. As an example, you could set ```sh export EXTRA_PLAYBOOK_OPTS="-vvv" ``` which would enable verbose logging for any of the ansible playbooks when we run `./pattern.sh make ` in any of our pattern repos. --- Makefile | 6 +++++- scripts/display-secrets-info.sh | 4 +++- scripts/load-k8s-secrets.sh | 4 +++- scripts/process-secrets.sh | 4 +++- scripts/vault-utils.sh | 4 +++- scripts/write-token-kubeconfig.sh | 4 +++- 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 4e977e10..84f6afc4 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,10 @@ endif # the command line. I.e. we can set things without having to tweak values files EXTRA_HELM_OPTS ?= +# This variable can be set in order to pass additional ansible-playbook arguments from the +# the command line. I.e. we can set -vvv for more verbose logging +EXTRA_PLAYBOOK_OPTS ?= + # INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:394248 # or # INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:394248,registry-proxy.engineering.redhat.com/rh-osbs/iib:394249 @@ -111,7 +115,7 @@ secrets-backend-none: ## Edits values files to remove secrets manager + ESO .PHONY: load-iib load-iib: ## CI target to install Index Image Bundles @set -e; if [ x$(INDEX_IMAGES) != x ]; then \ - ansible-playbook rhvp.cluster_utils.iib_ci; \ + ansible-playbook $(EXTRA_PLAYBOOK_OPTS) rhvp.cluster_utils.iib_ci; \ else \ echo "No INDEX_IMAGES defined. Bailing out"; \ exit 1; \ diff --git a/scripts/display-secrets-info.sh b/scripts/display-secrets-info.sh index d9915855..ca0069e2 100755 --- a/scripts/display-secrets-info.sh +++ b/scripts/display-secrets-info.sh @@ -23,4 +23,6 @@ fi PATTERN_NAME=$(basename "`pwd`") -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" -e override_no_log=false "rhvp.cluster_utils.display_secrets_info" +EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" + +ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" -e hide_sensitive_output=false ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.display_secrets_info" diff --git a/scripts/load-k8s-secrets.sh b/scripts/load-k8s-secrets.sh index 9219f92f..707e51a7 100755 --- a/scripts/load-k8s-secrets.sh +++ b/scripts/load-k8s-secrets.sh @@ -13,4 +13,6 @@ PATTERNPATH=$(dirname "${COMMONPATH}") PATTERN_NAME=${1:-$(basename "`pwd`")} -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "rhvp.cluster_utils.k8s_secrets" +EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" + +ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.k8s_secrets" diff --git a/scripts/process-secrets.sh b/scripts/process-secrets.sh index 47eff7fa..a0d34f88 100755 --- a/scripts/process-secrets.sh +++ b/scripts/process-secrets.sh @@ -14,4 +14,6 @@ PATTERNPATH=$(dirname "${COMMONPATH}") PATTERN_NAME=${1:-$(basename "`pwd`")} SECRETS_BACKING_STORE="$($SCRIPTPATH/determine-secretstore-backend.sh)" -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" "rhvp.cluster_utils.process_secrets" +EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" + +ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.process_secrets" diff --git a/scripts/vault-utils.sh b/scripts/vault-utils.sh index b014e5a4..2f766499 100755 --- a/scripts/vault-utils.sh +++ b/scripts/vault-utils.sh @@ -25,4 +25,6 @@ if [ -z ${TASK} ]; then exit 1 fi -ansible-playbook -t "${TASK}" -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "rhvp.cluster_utils.vault" +EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" + +ansible-playbook -t "${TASK}" -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.vault" diff --git a/scripts/write-token-kubeconfig.sh b/scripts/write-token-kubeconfig.sh index 7544fac2..e7913e53 100755 --- a/scripts/write-token-kubeconfig.sh +++ b/scripts/write-token-kubeconfig.sh @@ -13,4 +13,6 @@ SCRIPTPATH=$(dirname "${SCRIPT}") COMMONPATH=$(dirname "${SCRIPTPATH}") PATTERNPATH=$(dirname "${COMMONPATH}") -ansible-playbook -e pattern_dir="${PATTERNPATH}" -e kubeconfig_file="${OUTPUTFILE}" "rhvp.cluster_utils.write-token-kubeconfig" +EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" + +ansible-playbook -e pattern_dir="${PATTERNPATH}" -e kubeconfig_file="${OUTPUTFILE}" ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.write-token-kubeconfig" From ba9feab00e2b077c4db567feae4f9b5588333f64 Mon Sep 17 00:00:00 2001 From: Drew Minnear Date: Thu, 27 Feb 2025 09:58:09 -0500 Subject: [PATCH 220/222] update how to make common subtree A few small changes in this commit: * Update README to reference the `make-common-subtree` script in common rather than MCG repo * Update README and `make-common-subtree` script to use same default remote name for common subtree that we use in our `update-common-everywhere` script. * Update file name for the script to use dashes rather than underscores for consistency * Update the name of our GH org to `validatedpatterns` --- README.md | 10 +++++----- .../{make_common_subtree.sh => make-common-subtree.sh} | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) rename scripts/{make_common_subtree.sh => make-common-subtree.sh} (91%) diff --git a/README.md b/README.md index 41223529..b36bc1a4 100644 --- a/README.md +++ b/README.md @@ -34,16 +34,16 @@ main: ## Start Here This repository is never used as standalone. It is usually imported in each pattern as a subtree. -In order to import the common/ the very first time you can use -`https://github.com/validatedpatterns/multicloud-gitops/blob/main/common/scripts/make_common_subtree.sh` +In order to import the common subtree the very first time you can use the script +[make_common_subtree.sh](scripts/make-common-subtree.sh). In order to update your common subtree inside your pattern repository you can either use `https://github.com/validatedpatterns/utilities/blob/main/scripts/update-common-everywhere.sh` or -do it manually by doing the following: +do it manually with the following commands: ```sh -git remote add -f upstream-common https://github.com/validatedpatterns/common.git -git merge -s subtree -Xtheirs -Xsubtree=common upstream-common/main +git remote add -f common-upstream https://github.com/validatedpatterns/common.git +git merge -s subtree -Xtheirs -Xsubtree=common common-upstream/main ``` ## Secrets diff --git a/scripts/make_common_subtree.sh b/scripts/make-common-subtree.sh similarity index 91% rename from scripts/make_common_subtree.sh rename to scripts/make-common-subtree.sh index a5e406d8..196a4c8d 100755 --- a/scripts/make_common_subtree.sh +++ b/scripts/make-common-subtree.sh @@ -7,7 +7,7 @@ if [ "$1" = "-h" ]; then echo "$0 " echo echo "Run without arguments, the script would run as if these arguments had been passed:" - echo "$0 https://github.com/hybrid-cloud-patterns/common.git main common-subtree" + echo "$0 https://github.com/validatedpatterns/common.git main common-upstream" echo echo "Please ensure the git subtree command is available. On RHEL/Fedora, the git subtree command" echo "is in a separate package called git-subtree" @@ -41,7 +41,7 @@ fi if [ "$1" ]; then subtree_repo=$1 else - subtree_repo=https://github.com/hybrid-cloud-patterns/common.git + subtree_repo=https://github.com/validatedpatterns/common.git fi if [ "$2" ]; then @@ -53,7 +53,7 @@ fi if [ "$3" ]; then subtree_remote=$3 else - subtree_remote=common-subtree + subtree_remote=common-upstream fi git diff --quiet || (echo "This script must be run on a clean working tree" && exit 1) From b580b7fbdecc74f12be73b9379e1fbfea732cad1 Mon Sep 17 00:00:00 2001 From: Drew Minnear Date: Thu, 20 Mar 2025 15:01:45 -0400 Subject: [PATCH 221/222] Removed previous version of common to convert to subtree from https://github.com/validatedpatterns/common.git main --- common/.ansible-lint | 21 -- common/.github/dependabot.yml | 9 - common/.github/linters/.gitleaks.toml | 4 - common/.github/linters/.markdown-lint.yml | 6 - common/.github/workflows/superlinter.yml | 44 --- common/.gitignore | 13 - common/.gitleaks.toml | 1 - common/Changes.md | 153 ----------- common/LICENSE | 202 -------------- common/Makefile | 251 ------------------ common/README.md | 51 ---- common/requirements.yml | 4 - common/scripts/deploy-pattern.sh | 27 -- common/scripts/determine-main-clustergroup.sh | 16 -- common/scripts/determine-pattern-name.sh | 15 -- .../scripts/determine-secretstore-backend.sh | 15 -- common/scripts/display-secrets-info.sh | 26 -- common/scripts/load-k8s-secrets.sh | 16 -- common/scripts/make_common_subtree.sh | 76 ------ common/scripts/manage-secret-app.sh | 53 ---- common/scripts/manage-secret-namespace.sh | 28 -- common/scripts/pattern-util.sh | 111 -------- common/scripts/preview-all.sh | 25 -- common/scripts/preview.sh | 118 -------- common/scripts/process-secrets.sh | 17 -- common/scripts/set-secret-backend.sh | 5 - common/scripts/vault-utils.sh | 28 -- common/scripts/write-token-kubeconfig.sh | 16 -- 28 files changed, 1351 deletions(-) delete mode 100644 common/.ansible-lint delete mode 100644 common/.github/dependabot.yml delete mode 100644 common/.github/linters/.gitleaks.toml delete mode 100644 common/.github/linters/.markdown-lint.yml delete mode 100644 common/.github/workflows/superlinter.yml delete mode 100644 common/.gitignore delete mode 120000 common/.gitleaks.toml delete mode 100644 common/Changes.md delete mode 100644 common/LICENSE delete mode 100644 common/Makefile delete mode 100644 common/README.md delete mode 100644 common/requirements.yml delete mode 100755 common/scripts/deploy-pattern.sh delete mode 100755 common/scripts/determine-main-clustergroup.sh delete mode 100755 common/scripts/determine-pattern-name.sh delete mode 100755 common/scripts/determine-secretstore-backend.sh delete mode 100755 common/scripts/display-secrets-info.sh delete mode 100755 common/scripts/load-k8s-secrets.sh delete mode 100755 common/scripts/make_common_subtree.sh delete mode 100755 common/scripts/manage-secret-app.sh delete mode 100755 common/scripts/manage-secret-namespace.sh delete mode 100755 common/scripts/pattern-util.sh delete mode 100755 common/scripts/preview-all.sh delete mode 100755 common/scripts/preview.sh delete mode 100755 common/scripts/process-secrets.sh delete mode 100755 common/scripts/set-secret-backend.sh delete mode 100755 common/scripts/vault-utils.sh delete mode 100755 common/scripts/write-token-kubeconfig.sh diff --git a/common/.ansible-lint b/common/.ansible-lint deleted file mode 100644 index 0522976e..00000000 --- a/common/.ansible-lint +++ /dev/null @@ -1,21 +0,0 @@ -# Vim filetype=yaml ---- -offline: false -skip_list: - - name[template] # Allow Jinja templating inside task and play names - - template-instead-of-copy # Templated files should use template instead of copy - - yaml[line-length] # too long lines - - yaml[indentation] # Forcing lists to be always indented by 2 chars is silly IMO - - var-naming[no-role-prefix] # This would be too much churn for very little gain - - no-changed-when - - var-naming[no-role-prefix] # There are too many changes now and it would be too risky - -# ansible-lint gh workflow cannot find ansible.cfg hence fails to import vault_utils role -exclude_paths: - - ./ansible/playbooks/vault/vault.yaml - - ./ansible/playbooks/iib-ci/iib-ci.yaml - - ./ansible/playbooks/k8s_secrets/k8s_secrets.yml - - ./ansible/playbooks/process_secrets/process_secrets.yml - - ./ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml - - ./ansible/playbooks/process_secrets/display_secrets_info.yml - - ./ansible/roles/vault_utils/tests/test.yml diff --git a/common/.github/dependabot.yml b/common/.github/dependabot.yml deleted file mode 100644 index a175e666..00000000 --- a/common/.github/dependabot.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -version: 2 -updates: - # Check for updates to GitHub Actions every week - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - diff --git a/common/.github/linters/.gitleaks.toml b/common/.github/linters/.gitleaks.toml deleted file mode 100644 index 9ad74347..00000000 --- a/common/.github/linters/.gitleaks.toml +++ /dev/null @@ -1,4 +0,0 @@ -[whitelist] -# As of v4, gitleaks only matches against filename, not path in the -# files directive. Leaving content for backwards compatibility. -files = [ ] diff --git a/common/.github/linters/.markdown-lint.yml b/common/.github/linters/.markdown-lint.yml deleted file mode 100644 index a0bc47d1..00000000 --- a/common/.github/linters/.markdown-lint.yml +++ /dev/null @@ -1,6 +0,0 @@ -{ - "default": true, - "MD003": false, - "MD013": false, - "MD033": false -} \ No newline at end of file diff --git a/common/.github/workflows/superlinter.yml b/common/.github/workflows/superlinter.yml deleted file mode 100644 index 03b6fff9..00000000 --- a/common/.github/workflows/superlinter.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -name: Super linter - -on: [push, pull_request] - -jobs: - build: - # Name the Job - name: Super linter - # Set the agent to run on - runs-on: ubuntu-latest - - steps: - - name: Checkout Code - uses: actions/checkout@v4 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - ################################ - # Run Linter against code base # - ################################ - - name: Lint Code Base - uses: super-linter/super-linter/slim@v7 - env: - VALIDATE_ALL_CODEBASE: true - DEFAULT_BRANCH: main - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # These are the validation we disable atm - VALIDATE_ANSIBLE: false - VALIDATE_BASH: false - VALIDATE_CHECKOV: false - VALIDATE_JSCPD: false - VALIDATE_JSON_PRETTIER: false - VALIDATE_MARKDOWN_PRETTIER: false - VALIDATE_KUBERNETES_KUBECONFORM: false - VALIDATE_PYTHON_PYLINT: false - VALIDATE_SHELL_SHFMT: false - VALIDATE_YAML: false - VALIDATE_YAML_PRETTIER: false - # VALIDATE_DOCKERFILE_HADOLINT: false - # VALIDATE_MARKDOWN: false - # VALIDATE_NATURAL_LANGUAGE: false - # VALIDATE_TEKTON: false diff --git a/common/.gitignore b/common/.gitignore deleted file mode 100644 index 454efc9e..00000000 --- a/common/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -__pycache__/ -*.py[cod] -*~ -*.swp -*.swo -values-secret.yaml -.*.expected.yaml -.vscode -pattern-vault.init -pattern-vault.init.bak -super-linter.log -golang-external-secrets/Chart.lock -hashicorp-vault/Chart.lock diff --git a/common/.gitleaks.toml b/common/.gitleaks.toml deleted file mode 120000 index c05303b9..00000000 --- a/common/.gitleaks.toml +++ /dev/null @@ -1 +0,0 @@ -.github/linters/.gitleaks.toml \ No newline at end of file diff --git a/common/Changes.md b/common/Changes.md deleted file mode 100644 index c12f1755..00000000 --- a/common/Changes.md +++ /dev/null @@ -1,153 +0,0 @@ -# Changes - -## Sep 24, 2024 - -* Ansible has been moved out of the common code tree, you must use a clustergroup chart that is >= 0.9.1 - -## Sep 6, 2024 - -* Most charts have been removed from the tree. To get the charts you now have to point to them - -## Sep 25, 2023 - -* Upgraded ESO to v0.9.5 - -## Aug 17, 2023 - -* Introduced support for multisource applications via .chart + .chartVersion - -## Jul 8, 2023 - -* Introduced a default of 20 for sync failures retries in argo applications (global override via global.options.applicationRetryLimit - and per-app override via .syncPolicy) - -## May 22, 2023 - -* Upgraded ESO to 0.8.2 -* *Important* we now use the newly blessed sso config for argo. This means that gitops < 1.8 are *unsupported* - -## May 18, 2023 - -* Introduce a EXTRA_HELM_OPTS env variable that will be passed to the helm invocations - -## April 21, 2023 - -* Added labels and annotation support to namespaces.yaml template - -## Apr 11, 2023 - -* Apply the ACM ocp-gitops-policy everywhere but the hub - -## Apr 7, 2023 - -* Moved to gitops-1.8 channel by default (stable is unmaintained and will be dropped starting with ocp-4.13) - -## March 20, 2023 - -* Upgraded ESO to 0.8.1 - -## February 9, 2023 - -* Add support for /values-.yaml and for /values--.yaml - -## January 29, 2023 - -* Stop extracting the HUB's CA via an imperative job running on the imported cluster. - Just use ACM to push the HUB's CA out to the managed clusters. - -## January 23, 2023 - -* Add initial support for running ESO on ACM-imported clusters - -## January 18, 2023 - -* Add validate-schema target - -## January 13, 2023 - -* Simplify the secrets paths when using argo hosted sites - -## January 10, 2023 - -* vaultPrefixes is now optional in the v2 secret spec and defaults to ["hub"] - -## December 9, 2022 - -* Dropped insecureUnsealVaultInsideCluster (and file_unseal) entirely. Now - vault is always unsealed via a cronjob in the cluster. It is recommended to - store the imperative/vaultkeys secret offline securely and then delete it. - -## December 8, 2022 - -* Removed the legacy installation targets: - `deploy upgrade legacy-deploy legacy-upgrade` - Patterns must now use the operator-based installation - -## November 29, 2022 - -* Upgraded vault-helm to 0.23.0 -* Enable vault-ssl by default - -## November 22, 2022 - -* Implemented a new format for the values-secret.yaml. Example can be found in examples/ folder -* Now the order of values-secret file lookup is the following: - 1. ~/values-secret-.yaml - 2. ~/values-secret.yaml - 3. /values-secret.yaml.template -* Add support for ansible vault encrypted values-secret files. You can now encrypt your values-secret file - at rest with `ansible-vault encrypt ~/values-secret.yaml`. When running `make load-secrets` if an encrypted - file is encountered the user will be prompted automatically for the password to decrypt it. - -## November 6, 2022 - -* Add support for /values--.yaml (e.g. /values-AWS-group-one.yaml) - -## October 28, 2022 - -* Updated vault helm chart to v0.22.1 and vault containers to 1.12.0 - -## October 25, 2022 - -* Updated External Secrets Operator to v0.6.0 -* Moved to -UBI based ESO containers - -## October 13, 2022 - -* Added global.clusterVersion as a new helm variable which represents the OCP - Major.Minor cluster version. By default now a user can add a - values--.yaml file to have specific cluster version - overrides (e.g. values-4.10-hub.yaml). Will need Validated Patterns Operator >= 0.0.6 - when deploying with the operator. Note: When using the ArgoCD Hub and spoke model, - you cannot have spokes with a different version of OCP than the hub. - -## October 4, 2022 - -* Extended the values-secret.yaml file to support multiple vault paths and re-wrote - the push_secrets feature as python module plugin. This requires the following line - in a pattern's ansible.cfg's '[defaults]' stanza: - - `library=~/.ansible/plugins/modules:./ansible/plugins/modules:./common/ansible/plugins/modules:/usr/share/ansible/plugins/modules` - -## October 3, 2022 - -* Restore the ability to install a non-default site: `make TARGET_SITE=mysite install` -* Revised tests (new output and filenames, requires adding new result files to Git) -* ACM 2.6 required for ACM-based managed sites -* Introduced global.clusterDomain template variable (without the `apps.` prefix) -* Removed the ability to send specific charts to another cluster, use hosted argo sites instead -* Added the ability to have the hub host `values-{site}.yaml` for spoke clusters. - - The following example would deploy the namespaces, subscriptions, and - applications defined in `values-group-one.yaml` to the `perth` cluster - directly from ArgoCD on the hub. - - ```yaml - managedClusterGroups: - - name: group-one - hostedArgoSites: - - name: perth - domain: perth1.beekhof.net - bearerKeyPath: secret/data/hub/cluster_perth - caKeyPath: secret/data/hub/cluster_perth_ca - ``` diff --git a/common/LICENSE b/common/LICENSE deleted file mode 100644 index d6456956..00000000 --- a/common/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/common/Makefile b/common/Makefile deleted file mode 100644 index fc10236e..00000000 --- a/common/Makefile +++ /dev/null @@ -1,251 +0,0 @@ -NAME ?= $(shell basename "`pwd`") - -ifneq ($(origin TARGET_SITE), undefined) - TARGET_SITE_OPT=--set main.clusterGroupName=$(TARGET_SITE) -endif - -# This variable can be set in order to pass additional helm arguments from the -# the command line. I.e. we can set things without having to tweak values files -EXTRA_HELM_OPTS ?= - -# INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:394248 -# or -# INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:394248,registry-proxy.engineering.redhat.com/rh-osbs/iib:394249 -INDEX_IMAGES ?= - -TARGET_ORIGIN ?= origin -# This is to ensure that whether we start with a git@ or https:// URL, we end up with an https:// URL -# This is because we expect to use tokens for repo authentication as opposed to SSH keys -TARGET_REPO=$(shell git ls-remote --get-url --symref $(TARGET_ORIGIN) | sed -e 's/.*URL:[[:space:]]*//' -e 's%^git@%%' -e 's%^https://%%' -e 's%:%/%' -e 's%^%https://%') -# git branch --show-current is also available as of git 2.22, but we will use this for compatibility -TARGET_BRANCH=$(shell git rev-parse --abbrev-ref HEAD) - -UUID_FILE ?= ~/.config/validated-patterns/pattern-uuid -UUID_HELM_OPTS ?= - -# --set values always take precedence over the contents of -f -ifneq ("$(wildcard $(UUID_FILE))","") - UUID := $(shell cat $(UUID_FILE)) - UUID_HELM_OPTS := --set main.analyticsUUID=$(UUID) -endif - -# Set the secret name *and* its namespace when deploying from private repositories -# The format of said secret is documented here: https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#repositories -TOKEN_SECRET ?= -TOKEN_NAMESPACE ?= - -ifeq ($(TOKEN_SECRET),) - HELM_OPTS=-f values-global.yaml --set main.git.repoURL="$(TARGET_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(UUID_HELM_OPTS) $(EXTRA_HELM_OPTS) -else - # When we are working with a private repository we do not escape the git URL as it might be using an ssh secret which does not use https:// - TARGET_CLEAN_REPO=$(shell git ls-remote --get-url --symref $(TARGET_ORIGIN)) - HELM_OPTS=-f values-global.yaml --set main.tokenSecret=$(TOKEN_SECRET) --set main.tokenSecretNamespace=$(TOKEN_NAMESPACE) --set main.git.repoURL="$(TARGET_CLEAN_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(UUID_HELM_OPTS) $(EXTRA_HELM_OPTS) -endif - -# Helm does the right thing and fetches all the tags and detects the newest one -PATTERN_INSTALL_CHART ?= oci://quay.io/hybridcloudpatterns/pattern-install - -##@ Pattern Common Tasks - -.PHONY: help -help: ## This help message - @echo "Pattern: $(NAME)" - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^(\s|[a-zA-Z_0-9-])+:.*?##/ { printf " \033[36m%-35s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) - -# Makefiles in the individual patterns should call these targets explicitly -# e.g. from industrial-edge: make -f common/Makefile show -.PHONY: show -show: ## show the starting template without installing it - helm template $(PATTERN_INSTALL_CHART) --name-template $(NAME) $(HELM_OPTS) - -preview-all: ## (EXPERIMENTAL) Previews all applications on hub and managed clusters - @echo "NOTE: This is just a tentative approximation of rendering all hub and managed clusters templates" - @common/scripts/preview-all.sh $(TARGET_REPO) $(TARGET_BRANCH) - -preview-%: - $(eval CLUSTERGROUP ?= $(shell yq ".main.clusterGroupName" values-global.yaml)) - @common/scripts/preview.sh $(CLUSTERGROUP) $* $(TARGET_REPO) $(TARGET_BRANCH) - -.PHONY: operator-deploy -operator-deploy operator-upgrade: validate-prereq validate-origin validate-cluster ## runs helm install - @common/scripts/deploy-pattern.sh $(NAME) $(PATTERN_INSTALL_CHART) $(HELM_OPTS) - -.PHONY: uninstall -uninstall: ## runs helm uninstall - $(eval CSV := $(shell oc get subscriptions -n openshift-operators openshift-gitops-operator -ojsonpath={.status.currentCSV})) - helm uninstall $(NAME) - @oc delete csv -n openshift-operators $(CSV) - -.PHONY: load-secrets -load-secrets: ## loads the secrets into the backend determined by values-global setting - common/scripts/process-secrets.sh $(NAME) - -.PHONY: legacy-load-secrets -legacy-load-secrets: ## loads the secrets into vault (only) - common/scripts/vault-utils.sh push_secrets $(NAME) - -.PHONY: secrets-backend-vault -secrets-backend-vault: ## Edits values files to use default Vault+ESO secrets config - common/scripts/set-secret-backend.sh vault - common/scripts/manage-secret-app.sh vault present - common/scripts/manage-secret-app.sh golang-external-secrets present - common/scripts/manage-secret-namespace.sh validated-patterns-secrets absent - @git diff --exit-code || echo "Secrets backend set to vault, please review changes, commit, and push to activate in the pattern" - -.PHONY: secrets-backend-kubernetes -secrets-backend-kubernetes: ## Edits values file to use Kubernetes+ESO secrets config - common/scripts/set-secret-backend.sh kubernetes - common/scripts/manage-secret-namespace.sh validated-patterns-secrets present - common/scripts/manage-secret-app.sh vault absent - common/scripts/manage-secret-app.sh golang-external-secrets present - @git diff --exit-code || echo "Secrets backend set to kubernetes, please review changes, commit, and push to activate in the pattern" - -.PHONY: secrets-backend-none -secrets-backend-none: ## Edits values files to remove secrets manager + ESO - common/scripts/set-secret-backend.sh none - common/scripts/manage-secret-app.sh vault absent - common/scripts/manage-secret-app.sh golang-external-secrets absent - common/scripts/manage-secret-namespace.sh validated-patterns-secrets absent - @git diff --exit-code || echo "Secrets backend set to none, please review changes, commit, and push to activate in the pattern" - -.PHONY: load-iib -load-iib: ## CI target to install Index Image Bundles - @set -e; if [ x$(INDEX_IMAGES) != x ]; then \ - ansible-playbook rhvp.cluster_utils.iib_ci; \ - else \ - echo "No INDEX_IMAGES defined. Bailing out"; \ - exit 1; \ - fi - -.PHONY: token-kubeconfig -token-kubeconfig: ## Create a local ~/.kube/config with password (not usually needed) - common/scripts/write-token-kubeconfig.sh - -##@ Validation Tasks - -# We only check the remote ssh git branch's existance if we're not running inside a container -# as getting ssh auth working inside a container seems a bit brittle -# If the main repoUpstreamURL field is set, then we need to check against -# that and not target_repo -.PHONY: validate-origin -validate-origin: ## verify the git origin is available - @echo "Checking repository:" - $(eval UPSTREAMURL := $(shell yq -r '.main.git.repoUpstreamURL // (.main.git.repoUpstreamURL = "")' values-global.yaml)) - @if [ -z "$(UPSTREAMURL)" ]; then\ - echo -n " $(TARGET_REPO) - branch '$(TARGET_BRANCH)': ";\ - git ls-remote --exit-code --heads $(TARGET_REPO) $(TARGET_BRANCH) >/dev/null &&\ - echo "OK" || (echo "NOT FOUND"; exit 1);\ - else\ - echo "Upstream URL set to: $(UPSTREAMURL)";\ - echo -n " $(UPSTREAMURL) - branch '$(TARGET_BRANCH)': ";\ - git ls-remote --exit-code --heads $(UPSTREAMURL) $(TARGET_BRANCH) >/dev/null &&\ - echo "OK" || (echo "NOT FOUND"; exit 1);\ - fi - -.PHONY: validate-cluster -validate-cluster: ## Do some cluster validations before installing - @echo "Checking cluster:" - @echo -n " cluster-info: " - @oc cluster-info >/dev/null && echo "OK" || (echo "Error"; exit 1) - @echo -n " storageclass: " - @if [ `oc get storageclass -o go-template='{{printf "%d\n" (len .items)}}'` -eq 0 ]; then\ - echo "WARNING: No storageclass found";\ - else\ - echo "OK";\ - fi - - -.PHONY: validate-schema -validate-schema: ## validates values files against schema in common/clustergroup - $(eval VAL_PARAMS := $(shell for i in ./values-*.yaml; do echo -n "$${i} "; done)) - @echo -n "Validating clustergroup schema of: " - @set -e; for i in $(VAL_PARAMS); do echo -n " $$i"; helm template oci://quay.io/hybridcloudpatterns/clustergroup $(HELM_OPTS) -f "$${i}" >/dev/null; done - @echo - -.PHONY: validate-prereq -validate-prereq: ## verify pre-requisites - $(eval GLOBAL_PATTERN := $(shell yq -r .global.pattern values-global.yaml)) - @if [ $(NAME) != $(GLOBAL_PATTERN) ]; then\ - echo "";\ - echo "WARNING: folder directory is \"$(NAME)\" and global.pattern is set to \"$(GLOBAL_PATTERN)\"";\ - echo "this can create problems. Please make sure they are the same!";\ - echo "";\ - fi - @if [ ! -f /run/.containerenv ]; then\ - echo "Checking prerequisites:";\ - echo -n " Check for python-kubernetes: ";\ - if ! ansible -m ansible.builtin.command -a "{{ ansible_python_interpreter }} -c 'import kubernetes'" localhost > /dev/null 2>&1; then echo "Not found"; exit 1; fi;\ - echo "OK";\ - echo -n " Check for kubernetes.core collection: ";\ - if ! ansible-galaxy collection list | grep kubernetes.core > /dev/null 2>&1; then echo "Not found"; exit 1; fi;\ - echo "OK";\ - else\ - if [ -f values-global.yaml ]; then\ - OUT=`yq -r '.main.multiSourceConfig.enabled // (.main.multiSourceConfig.enabled = "false")' values-global.yaml`;\ - if [ "$${OUT,,}" = "false" ]; then\ - echo "You must set \".main.multiSourceConfig.enabled: true\" in your 'values-global.yaml' file";\ - echo "because your common subfolder is the slimmed down version with no helm charts in it";\ - exit 1;\ - fi;\ - fi;\ - fi - -.PHONY: argo-healthcheck -argo-healthcheck: ## Checks if all argo applications are synced - @echo "Checking argo applications" - $(eval APPS := $(shell oc get applications.argoproj.io -A -o jsonpath='{range .items[*]}{@.metadata.namespace}{","}{@.metadata.name}{"\n"}{end}')) - @NOTOK=0; \ - for i in $(APPS); do\ - n=`echo "$${i}" | cut -f1 -d,`;\ - a=`echo "$${i}" | cut -f2 -d,`;\ - STATUS=`oc get -n "$${n}" applications.argoproj.io/"$${a}" -o jsonpath='{.status.sync.status}'`;\ - if [[ $$STATUS != "Synced" ]]; then\ - NOTOK=$$(( $${NOTOK} + 1));\ - fi;\ - HEALTH=`oc get -n "$${n}" applications.argoproj.io/"$${a}" -o jsonpath='{.status.health.status}'`;\ - if [[ $$HEALTH != "Healthy" ]]; then\ - NOTOK=$$(( $${NOTOK} + 1));\ - fi;\ - echo "$${n} $${a} -> Sync: $${STATUS} - Health: $${HEALTH}";\ - done;\ - if [ $${NOTOK} -gt 0 ]; then\ - echo "Some applications are not synced or are unhealthy";\ - exit 1;\ - fi - - -##@ Test and Linters Tasks - -.PHONY: qe-tests -qe-tests: ## Runs the tests that QE runs - @set -e; if [ -f ./tests/interop/run_tests.sh ]; then \ - pushd ./tests/interop; ./run_tests.sh; popd; \ - else \ - echo "No ./tests/interop/run_tests.sh found skipping"; \ - fi - -.PHONY: super-linter -super-linter: ## Runs super linter locally - rm -rf .mypy_cache - podman run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true \ - -e VALIDATE_ANSIBLE=false \ - -e VALIDATE_BASH=false \ - -e VALIDATE_CHECKOV=false \ - -e VALIDATE_DOCKERFILE_HADOLINT=false \ - -e VALIDATE_JSCPD=false \ - -e VALIDATE_JSON_PRETTIER=false \ - -e VALIDATE_MARKDOWN_PRETTIER=false \ - -e VALIDATE_KUBERNETES_KUBECONFORM=false \ - -e VALIDATE_PYTHON_PYLINT=false \ - -e VALIDATE_SHELL_SHFMT=false \ - -e VALIDATE_TEKTON=false \ - -e VALIDATE_YAML=false \ - -e VALIDATE_YAML_PRETTIER=false \ - $(DISABLE_LINTERS) \ - -v $(PWD):/tmp/lint:rw,z \ - -w /tmp/lint \ - ghcr.io/super-linter/super-linter:slim-v7 - -.PHONY: deploy upgrade legacy-deploy legacy-upgrade -deploy upgrade legacy-deploy legacy-upgrade: - @echo "UNSUPPORTED TARGET: please switch to 'operator-deploy'"; exit 1 diff --git a/common/README.md b/common/README.md deleted file mode 100644 index 41223529..00000000 --- a/common/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# Validated Patterns common/ repository - -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) - -## Note - -This is the `main` branch of common and it assumes that the pattern is fully -multisource (meaning that any used charts from VP is actually referenced from -either a helm chart repository or quay repository). I.e. there are no helm -charts contained in this branch of common and there is no ansible code neither. - -The helm charts now live in separate repositories under the VP -[organization](https://github.com/validatedpatterns) on GitHub. The repositories are: - -- clustergroup-chart -- pattern-install-chart -- hashicorp-vault-chart -- golang-external-secrets-chart -- acm-chart -- letsencrypt-chart - -The ansible bits live in this [repository](https://github.com/validatedpatterns/rhvp.cluster_utils) - -In order to be able to use this "slimmed-down" main branch of common you *must* -use a 0.9.* clustergroup-chart that. Add the following to your `values-global.yaml`: - -```yaml -main: - multiSourceConfig: - enabled: true - clusterGroupChartVersion: 0.9.* -``` - -## Start Here - -This repository is never used as standalone. It is usually imported in each pattern as a subtree. -In order to import the common/ the very first time you can use -`https://github.com/validatedpatterns/multicloud-gitops/blob/main/common/scripts/make_common_subtree.sh` - -In order to update your common subtree inside your pattern repository you can either use -`https://github.com/validatedpatterns/utilities/blob/main/scripts/update-common-everywhere.sh` or -do it manually by doing the following: - -```sh -git remote add -f upstream-common https://github.com/validatedpatterns/common.git -git merge -s subtree -Xtheirs -Xsubtree=common upstream-common/main -``` - -## Secrets - -There are two different secret formats parsed by the ansible bits. Both are documented [here](https://github.com/validatedpatterns/common/tree/main/ansible/roles/vault_utils/README.md) diff --git a/common/requirements.yml b/common/requirements.yml deleted file mode 100644 index cb11ca24..00000000 --- a/common/requirements.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -# Define Ansible collection requirements here -collections: - - name: git+https://github.com/validatedpatterns/rhvp.cluster_utils.git,v1 diff --git a/common/scripts/deploy-pattern.sh b/common/scripts/deploy-pattern.sh deleted file mode 100755 index 61074fe1..00000000 --- a/common/scripts/deploy-pattern.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -set -o pipefail - -RUNS=10 -WAIT=15 -# Retry five times because the CRD might not be fully installed yet -echo -n "Installing pattern: " -for i in $(seq 1 ${RUNS}); do \ - exec 3>&1 4>&2 - OUT=$( { helm template --include-crds --name-template $* 2>&4 | oc apply -f- 2>&4 1>&3; } 4>&1 3>&1) - ret=$? - exec 3>&- 4>&- - if [ ${ret} -eq 0 ]; then - break; - else - echo -n "." - sleep "${WAIT}" - fi -done - -# All the runs failed -if [ ${i} -eq ${RUNS} ]; then - echo "Installation failed [${i}/${RUNS}]. Error:" - echo "${OUT}" - exit 1 -fi -echo "Done" diff --git a/common/scripts/determine-main-clustergroup.sh b/common/scripts/determine-main-clustergroup.sh deleted file mode 100755 index 6271dbad..00000000 --- a/common/scripts/determine-main-clustergroup.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -PATTERN_DIR="$1" - -if [ -z "$PATTERN_DIR" ]; then - PATTERN_DIR="." -fi - -CGNAME=$(yq '.main.clusterGroupName' "$PATTERN_DIR/values-global.yaml") - -if [ -z "$CGNAME" ] || [ "$CGNAME" == "null" ]; then - echo "Error - cannot detrmine clusterGroupName" - exit 1 -fi - -echo "$CGNAME" diff --git a/common/scripts/determine-pattern-name.sh b/common/scripts/determine-pattern-name.sh deleted file mode 100755 index fb503fe6..00000000 --- a/common/scripts/determine-pattern-name.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -PATTERN_DIR="$1" - -if [ -z "$PATTERN_DIR" ]; then - PATTERN_DIR="." -fi - -PATNAME=$(yq '.global.pattern' "$PATTERN_DIR/values-global.yaml" 2>/dev/null) - -if [ -z "$PATNAME" ] || [ "$PATNAME" == "null" ]; then - PATNAME="$(basename "$PWD")" -fi - -echo "$PATNAME" diff --git a/common/scripts/determine-secretstore-backend.sh b/common/scripts/determine-secretstore-backend.sh deleted file mode 100755 index ef784790..00000000 --- a/common/scripts/determine-secretstore-backend.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -PATTERN_DIR="$1" - -if [ -z "$PATTERN_DIR" ]; then - PATTERN_DIR="." -fi - -BACKEND=$(yq '.global.secretStore.backend' "$PATTERN_DIR/values-global.yaml" 2>/dev/null) - -if [ -z "$BACKEND" -o "$BACKEND" == "null" ]; then - BACKEND="vault" -fi - -echo "$BACKEND" diff --git a/common/scripts/display-secrets-info.sh b/common/scripts/display-secrets-info.sh deleted file mode 100755 index d9915855..00000000 --- a/common/scripts/display-secrets-info.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -set -eu - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -if [ "$#" -ge 1 ]; then - export VALUES_SECRET=$(get_abs_filename "${1}") -fi - -if [[ "$#" == 2 ]]; then - SECRETS_BACKING_STORE="$2" -else - SECRETS_BACKING_STORE="$($SCRIPTPATH/determine-secretstore-backend.sh)" -fi - -PATTERN_NAME=$(basename "`pwd`") - -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" -e override_no_log=false "rhvp.cluster_utils.display_secrets_info" diff --git a/common/scripts/load-k8s-secrets.sh b/common/scripts/load-k8s-secrets.sh deleted file mode 100755 index 9219f92f..00000000 --- a/common/scripts/load-k8s-secrets.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -set -eu - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -PATTERN_NAME=${1:-$(basename "`pwd`")} - -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "rhvp.cluster_utils.k8s_secrets" diff --git a/common/scripts/make_common_subtree.sh b/common/scripts/make_common_subtree.sh deleted file mode 100755 index a5e406d8..00000000 --- a/common/scripts/make_common_subtree.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh - -if [ "$1" = "-h" ]; then - echo "This script will convert common into a subtree and add a remote to help manage it." - echo "The script takes three positional arguments, as follows:" - echo - echo "$0 " - echo - echo "Run without arguments, the script would run as if these arguments had been passed:" - echo "$0 https://github.com/hybrid-cloud-patterns/common.git main common-subtree" - echo - echo "Please ensure the git subtree command is available. On RHEL/Fedora, the git subtree command" - echo "is in a separate package called git-subtree" - exit 1 -fi - -if [ -f '/etc/redhat-release' ]; then - rpm -qa | grep git-subtree 2>&1 - if [ ! $? = 0 ]; then - echo "you need to install git-subtree" - echo "would you like to install it now?" - select ANS in yes no - do - case $ANS in - yes) - sudo dnf install git-subtree -y - break - ;; - no) - exit - break - ;; - *) - echo "You must enter yes or no" - ;; - esac - done - fi -fi - -if [ "$1" ]; then - subtree_repo=$1 -else - subtree_repo=https://github.com/hybrid-cloud-patterns/common.git -fi - -if [ "$2" ]; then - subtree_branch=$2 -else - subtree_branch=main -fi - -if [ "$3" ]; then - subtree_remote=$3 -else - subtree_remote=common-subtree -fi - -git diff --quiet || (echo "This script must be run on a clean working tree" && exit 1) - -echo "Changing directory to project root" -cd `git rev-parse --show-toplevel` - -echo "Removing existing common and replacing it with subtree from $subtree_repo $subtree_remote" -rm -rf common - -echo "Committing removal of common" -(git add -A :/ && git commit -m "Removed previous version of common to convert to subtree from $subtree_repo $subtree_branch") || exit 1 - -echo "Adding (possibly replacing) subtree remote $subtree_remote" -git remote rm "$subtree_remote" -git remote add -f "$subtree_remote" "$subtree_repo" || exit 1 -git subtree add --prefix=common "$subtree_remote" "$subtree_branch" || exit 1 - -echo "Complete. You may now push these results if you are satisfied" -exit 0 diff --git a/common/scripts/manage-secret-app.sh b/common/scripts/manage-secret-app.sh deleted file mode 100755 index 18a986e5..00000000 --- a/common/scripts/manage-secret-app.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh - -APP=$1 -STATE=$2 - -MAIN_CLUSTERGROUP_FILE="./values-$(common/scripts/determine-main-clustergroup.sh).yaml" -MAIN_CLUSTERGROUP_PROJECT="$(common/scripts/determine-main-clustergroup.sh)" - -case "$APP" in - "vault") - APP_NAME="vault" - NAMESPACE="vault" - PROJECT="$MAIN_CLUSTERGROUP_PROJECT" - CHART_NAME="hashicorp-vault" - CHART_VERSION=0.1.* - - ;; - "golang-external-secrets") - APP_NAME="golang-external-secrets" - NAMESPACE="golang-external-secrets" - PROJECT="$MAIN_CLUSTERGROUP_PROJECT" - CHART_NAME="golang-external-secrets" - CHART_VERSION=0.1.* - - ;; - *) - echo "Error - cannot manage $APP can only manage vault and golang-external-secrets" - exit 1 - ;; -esac - -case "$STATE" in - "present") - common/scripts/manage-secret-namespace.sh "$NAMESPACE" "$STATE" - - RES=$(yq ".clusterGroup.applications[] | select(.path == \"$CHART_LOCATION\")" "$MAIN_CLUSTERGROUP_FILE" 2>/dev/null) - if [ -z "$RES" ]; then - echo "Application with chart location $CHART_LOCATION not found, adding" - yq -i ".clusterGroup.applications.$APP_NAME = { \"name\": \"$APP_NAME\", \"namespace\": \"$NAMESPACE\", \"project\": \"$PROJECT\", \"chart\": \"$CHART_NAME\", \"chartVersion\": \"$CHART_VERSION\"}" "$MAIN_CLUSTERGROUP_FILE" - fi - ;; - "absent") - common/scripts/manage-secret-namespace.sh "$NAMESPACE" "$STATE" - echo "Removing application wth chart location $CHART_LOCATION" - yq -i "del(.clusterGroup.applications[] | select(.chart == \"$CHART_NAME\"))" "$MAIN_CLUSTERGROUP_FILE" - ;; - *) - echo "$STATE not supported" - exit 1 - ;; -esac - -exit 0 diff --git a/common/scripts/manage-secret-namespace.sh b/common/scripts/manage-secret-namespace.sh deleted file mode 100755 index bcb06742..00000000 --- a/common/scripts/manage-secret-namespace.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -NAMESPACE=$1 -STATE=$2 - -MAIN_CLUSTERGROUP_FILE="./values-$(common/scripts/determine-main-clustergroup.sh).yaml" -MAIN_CLUSTERGROUP_PROJECT="$(common/scripts/determine-main-clustergroup.sh)" - -case "$STATE" in - "present") - - RES=$(yq ".clusterGroup.namespaces[] | select(. == \"$NAMESPACE\")" "$MAIN_CLUSTERGROUP_FILE" 2>/dev/null) - if [ -z "$RES" ]; then - echo "Namespace $NAMESPACE not found, adding" - yq -i ".clusterGroup.namespaces += [ \"$NAMESPACE\" ]" "$MAIN_CLUSTERGROUP_FILE" - fi - ;; - "absent") - echo "Removing namespace $NAMESPACE" - yq -i "del(.clusterGroup.namespaces[] | select(. == \"$NAMESPACE\"))" "$MAIN_CLUSTERGROUP_FILE" - ;; - *) - echo "$STATE not supported" - exit 1 - ;; -esac - -exit 0 diff --git a/common/scripts/pattern-util.sh b/common/scripts/pattern-util.sh deleted file mode 100755 index 27b30229..00000000 --- a/common/scripts/pattern-util.sh +++ /dev/null @@ -1,111 +0,0 @@ -#!/bin/bash - -function is_available { - command -v $1 >/dev/null 2>&1 || { echo >&2 "$1 is required but it's not installed. Aborting."; exit 1; } -} - -function version { - echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' -} - -if [ -z "$PATTERN_UTILITY_CONTAINER" ]; then - PATTERN_UTILITY_CONTAINER="quay.io/hybridcloudpatterns/utility-container" -fi -# If PATTERN_DISCONNECTED_HOME is set it will be used to populate both PATTERN_UTILITY_CONTAINER -# and PATTERN_INSTALL_CHART automatically -if [ -n "${PATTERN_DISCONNECTED_HOME}" ]; then - PATTERN_UTILITY_CONTAINER="${PATTERN_DISCONNECTED_HOME}/utility-container" - PATTERN_INSTALL_CHART="oci://${PATTERN_DISCONNECTED_HOME}/pattern-install" - echo "PATTERN_DISCONNECTED_HOME is set to ${PATTERN_DISCONNECTED_HOME}" - echo "Setting the following variables:" - echo " PATTERN_UTILITY_CONTAINER: ${PATTERN_UTILITY_CONTAINER}" - echo " PATTERN_INSTALL_CHART: ${PATTERN_INSTALL_CHART}" -fi - -readonly commands=(podman) -for cmd in ${commands[@]}; do is_available "$cmd"; done - -UNSUPPORTED_PODMAN_VERSIONS="1.6 1.5" -PODMAN_VERSION_STR=$(podman --version) -for i in ${UNSUPPORTED_PODMAN_VERSIONS}; do - # We add a space - if echo "${PODMAN_VERSION_STR}" | grep -q -E "\b${i}"; then - echo "Unsupported podman version. We recommend > 4.3.0" - podman --version - exit 1 - fi -done - -# podman --version outputs: -# podman version 4.8.2 -PODMAN_VERSION=$(echo "${PODMAN_VERSION_STR}" | awk '{ print $NF }') - -# podman < 4.3.0 do not support keep-id:uid=... -if [ $(version "${PODMAN_VERSION}") -lt $(version "4.3.0") ]; then - PODMAN_ARGS="-v ${HOME}:/root" -else - # We do not rely on bash's $UID and $GID because on MacOSX $GID is not set - MYNAME=$(id -n -u) - MYUID=$(id -u) - MYGID=$(id -g) - PODMAN_ARGS="--passwd-entry ${MYNAME}:x:${MYUID}:${MYGID}::/pattern-home:/bin/bash --user ${MYUID}:${MYGID} --userns keep-id:uid=${MYUID},gid=${MYGID}" - -fi - -if [ -n "$KUBECONFIG" ]; then - if [[ ! "${KUBECONFIG}" =~ ^$HOME* ]]; then - echo "${KUBECONFIG} is pointing outside of the HOME folder, this will make it unavailable from the container." - echo "Please move it somewhere inside your $HOME folder, as that is what gets bind-mounted inside the container" - exit 1 - fi -fi - -# Detect if we use podman machine. If we do not then we bind mount local host ssl folders -# if we are using podman machine then we do not bind mount anything (for now!) -REMOTE_PODMAN=$(podman system connection list -q | wc -l) -if [ $REMOTE_PODMAN -eq 0 ]; then # If we are not using podman machine we check the hosts folders - # We check /etc/pki/tls because on ubuntu /etc/pki/fwupd sometimes - # exists but not /etc/pki/tls and we do not want to bind mount in such a case - # as it would find no certificates at all. - if [ -d /etc/pki/tls ]; then - PKI_HOST_MOUNT_ARGS="-v /etc/pki:/etc/pki:ro" - elif [ -d /etc/ssl ]; then - PKI_HOST_MOUNT_ARGS="-v /etc/ssl:/etc/ssl:ro" - else - PKI_HOST_MOUNT_ARGS="-v /usr/share/ca-certificates:/usr/share/ca-certificates:ro" - fi -else - PKI_HOST_MOUNT_ARGS="" -fi - -# Copy Kubeconfig from current environment. The utilities will pick up ~/.kube/config if set so it's not mandatory -# $HOME is mounted as itself for any files that are referenced with absolute paths -# $HOME is mounted to /root because the UID in the container is 0 and that's where SSH looks for credentials - -podman run -it --rm --pull=newer \ - --security-opt label=disable \ - -e EXTRA_HELM_OPTS \ - -e EXTRA_PLAYBOOK_OPTS \ - -e TARGET_ORIGIN \ - -e TARGET_SITE \ - -e NAME \ - -e TOKEN_SECRET \ - -e TOKEN_NAMESPACE \ - -e VALUES_SECRET \ - -e KUBECONFIG \ - -e PATTERN_INSTALL_CHART \ - -e PATTERN_DISCONNECTED_HOME \ - -e K8S_AUTH_HOST \ - -e K8S_AUTH_VERIFY_SSL \ - -e K8S_AUTH_SSL_CA_CERT \ - -e K8S_AUTH_USERNAME \ - -e K8S_AUTH_PASSWORD \ - -e K8S_AUTH_TOKEN \ - ${PKI_HOST_MOUNT_ARGS} \ - -v "${HOME}":"${HOME}" \ - -v "${HOME}":/pattern-home \ - ${PODMAN_ARGS} \ - ${EXTRA_ARGS} \ - -w "$(pwd)" \ - "$PATTERN_UTILITY_CONTAINER" \ - $@ diff --git a/common/scripts/preview-all.sh b/common/scripts/preview-all.sh deleted file mode 100755 index 4bf59322..00000000 --- a/common/scripts/preview-all.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -REPO=$1; shift; -TARGET_BRANCH=$1; shift - -HUB=$( yq ".main.clusterGroupName" values-global.yaml ) -MANAGED_CLUSTERS=$( yq ".clusterGroup.managedClusterGroups.[].name" values-$HUB.yaml ) -ALL_CLUSTERS=( $HUB $MANAGED_CLUSTERS ) - -CLUSTER_INFO_OUT=$(oc cluster-info 2>&1) -CLUSTER_INFO_RET=$? -if [ $CLUSTER_INFO_RET -ne 0 ]; then - echo "Could not access the cluster:" - echo "${CLUSTER_INFO_OUT}" - exit 1 -fi - -for cluster in ${ALL_CLUSTERS[@]}; do - # We always add clustergroup as it is the entry point and it gets special cased in preview.sh. - APPS="clustergroup $( yq ".clusterGroup.applications.[].name" values-$cluster.yaml )" - for app in $APPS; do - printf "# Parsing application $app from cluster $cluster\n" - common/scripts/preview.sh $cluster $app $REPO $TARGET_BRANCH - done -done diff --git a/common/scripts/preview.sh b/common/scripts/preview.sh deleted file mode 100755 index 6da45785..00000000 --- a/common/scripts/preview.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/bash - -# DISCLAIMER -# -# - Parsing of applications needs to be more clever. -# - There is currently not a mechanism to actually preview against multiple clusters -# (i.e. a hub and a remote). All previews will be done against the current. -# - Make output can be included in the YAML. - -SITE=$1; shift -APPNAME=$1; shift -GIT_REPO=$1; shift -GIT_BRANCH=$1; shift - -if [ "${APPNAME}" != "clustergroup" ]; then - # This covers the following case: - # foobar: - # name: foo - # namespace: foo - # project: foo - # path: charts/all/foo - # So we retrieve the actual index ("foobar") given the name attribute of the application - APP=$(yq ".clusterGroup.applications | with_entries(select(.value.name == \"$APPNAME\")) | keys | .[0]" values-$SITE.yaml) - isLocalHelmChart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) - if [ $isLocalHelmChart != "null" ]; then - chart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) - else - helmrepo=$(yq ".clusterGroup.applications.$APP.repoURL" values-$SITE.yaml) - helmrepo="${helmrepo:+oci://quay.io/hybridcloudpatterns}" - chartversion=$(yq ".clusterGroup.applications.$APP.chartVersion" values-$SITE.yaml) - chartname=$(yq ".clusterGroup.applications.$APP.chart" values-$SITE.yaml) - chart="${helmrepo}/${chartname} --version ${chartversion}" - fi - namespace=$(yq ".clusterGroup.applications.$APP.namespace" values-$SITE.yaml) -else - APP=$APPNAME - clusterGroupChartVersion=$(yq ".main.multiSourceConfig.clusterGroupChartVersion" values-global.yaml) - helmrepo="oci://quay.io/hybridcloudpatterns" - chart="${helmrepo}/clustergroup --version ${clusterGroupChartVersion}" - namespace="openshift-operators" -fi -pattern=$(yq ".global.pattern" values-global.yaml) - -# You can override the default lookups by using OCP_{PLATFORM,VERSION,DOMAIN} -# Note that when using the utility container you need to pass in the above variables -# by export EXTRA_ARGS="-e OCP_PLATFORM -e OCP_VERSION -e OCP_DOMAIN" before -# invoking pattern-util.sh -platform=${OCP_PLATFORM:-$(oc get Infrastructure.config.openshift.io/cluster -o jsonpath='{.spec.platformSpec.type}')} -ocpversion=${OCP_VERSION:-$(oc get clusterversion/version -o jsonpath='{.status.desired.version}' | awk -F. '{print $1"."$2}')} -domain=${OCP_DOMAIN:-$(oc get Ingress.config.openshift.io/cluster -o jsonpath='{.spec.domain}' | sed 's/^apps.//')} - -function replaceGlobals() { - output=$( echo $1 | sed -e 's/ //g' -e 's/\$//g' -e s@^-@@g -e s@\'@@g ) - - output=$(echo $output | sed "s@{{.Values.global.clusterPlatform}}@${platform}@g") - output=$(echo $output | sed "s@{{.Values.global.clusterVersion}}@${ocpversion}@g") - output=$(echo $output | sed "s@{{.Values.global.clusterDomain}}@${domain}@g") - - echo $output -} - -function getOverrides() { - overrides='' - overrides=$( yq ".clusterGroup.applications.$APP.overrides[]" "values-$SITE.yaml" ) - overrides=$( echo "$overrides" | tr -d '\n' ) - overrides=$( echo "$overrides" | sed -e 's/name:/ --set/g; s/value: /=/g' ) - if [ -n "$overrides" ]; then - echo "$overrides" - fi -} - - -CLUSTER_OPTS="" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.pattern=$pattern" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.repoURL=$GIT_REPO" -CLUSTER_OPTS="$CLUSTER_OPTS --set main.git.repoURL=$GIT_REPO" -CLUSTER_OPTS="$CLUSTER_OPTS --set main.git.revision=$GIT_BRANCH" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.namespace=$namespace" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.hubClusterDomain=apps.$domain" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.localClusterDomain=apps.$domain" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.clusterDomain=$domain" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.clusterVersion=$ocpversion" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.clusterPlatform=$platform" - - -sharedValueFiles=$(yq ".clusterGroup.sharedValueFiles" values-$SITE.yaml) -appValueFiles=$(yq ".clusterGroup.applications.$APP.extraValueFiles" values-$SITE.yaml) -isKustomize=$(yq ".clusterGroup.applications.$APP.kustomize" values-$SITE.yaml) -OVERRIDES=$( getOverrides ) - -VALUE_FILES="-f values-global.yaml -f values-$SITE.yaml" -IFS=$'\n' -for line in $sharedValueFiles; do - if [ $line != "null" ] && [ -f $line ]; then - file=$(replaceGlobals $line) - VALUE_FILES="$VALUE_FILES -f $PWD$file" - fi -done - -for line in $appValueFiles; do - if [ $line != "null" ] && [ -f $line ]; then - file=$(replaceGlobals $line) - VALUE_FILES="$VALUE_FILES -f $PWD$file" - fi -done - -if [ $isKustomize == "true" ]; then - kustomizePath=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) - repoURL=$(yq ".clusterGroup.applications.$APP.repoURL" values-$SITE.yaml) - if [[ $repoURL == http* ]] || [[ $repoURL == git@ ]]; then - kustomizePath="${repoURL}/${kustomizePath}" - fi - cmd="oc kustomize ${kustomizePath}" - eval "$cmd" -else - cmd="helm template $chart --name-template ${APP} -n ${namespace} ${VALUE_FILES} ${OVERRIDES} ${CLUSTER_OPTS}" - eval "$cmd" -fi diff --git a/common/scripts/process-secrets.sh b/common/scripts/process-secrets.sh deleted file mode 100755 index 47eff7fa..00000000 --- a/common/scripts/process-secrets.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -set -eu - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -PATTERN_NAME=${1:-$(basename "`pwd`")} -SECRETS_BACKING_STORE="$($SCRIPTPATH/determine-secretstore-backend.sh)" - -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" "rhvp.cluster_utils.process_secrets" diff --git a/common/scripts/set-secret-backend.sh b/common/scripts/set-secret-backend.sh deleted file mode 100755 index e07b15bf..00000000 --- a/common/scripts/set-secret-backend.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -BACKEND=$1 - -yq -i ".global.secretStore.backend = \"$BACKEND\"" values-global.yaml diff --git a/common/scripts/vault-utils.sh b/common/scripts/vault-utils.sh deleted file mode 100755 index b014e5a4..00000000 --- a/common/scripts/vault-utils.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash -set -eu - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -# Parse arguments -if [ $# -lt 1 ]; then - echo "Specify at least the command ($#): $*" - exit 1 -fi - -TASK="${1}" -PATTERN_NAME=${2:-$(basename "`pwd`")} - -if [ -z ${TASK} ]; then - echo "Task is unset" - exit 1 -fi - -ansible-playbook -t "${TASK}" -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" "rhvp.cluster_utils.vault" diff --git a/common/scripts/write-token-kubeconfig.sh b/common/scripts/write-token-kubeconfig.sh deleted file mode 100755 index 7544fac2..00000000 --- a/common/scripts/write-token-kubeconfig.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -set -eu - -OUTPUTFILE=${1:-"~/.kube/config"} - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -ansible-playbook -e pattern_dir="${PATTERNPATH}" -e kubeconfig_file="${OUTPUTFILE}" "rhvp.cluster_utils.write-token-kubeconfig" From 094354b4420749ae16efdc0214f805a37eb7064d Mon Sep 17 00:00:00 2001 From: Drew Minnear Date: Thu, 20 Mar 2025 15:06:32 -0400 Subject: [PATCH 222/222] use operand image for nfd based on openshift cluster version --- charts/all/nfd-config/templates/node-feature-discovery.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/charts/all/nfd-config/templates/node-feature-discovery.yaml b/charts/all/nfd-config/templates/node-feature-discovery.yaml index 8d697082..484fbad1 100644 --- a/charts/all/nfd-config/templates/node-feature-discovery.yaml +++ b/charts/all/nfd-config/templates/node-feature-discovery.yaml @@ -6,7 +6,7 @@ metadata: spec: operand: image: >- - registry.redhat.io/openshift4/ose-node-feature-discovery@sha256:5f92998549dccf26d07138c2f556444e8a81ac41e53a398d9c3f43bc31c20a47 + registry.redhat.io/openshift4/ose-node-feature-discovery-rhel9:v{{ .Values.global.clusterVersion }} servicePort: 12000 workerConfig: configData: | @@ -116,4 +116,3 @@ spec: # vendor: ["15b3"] # device: ["1014", "1017"] # loadedKMod : ["vendor_kmod1", "vendor_kmod2"] -

e9?vX&2{P`z*yEQ@&1J8iL1Z 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 Ls1SjK0N4Zo6jePG diff --git a/hashicorp-vault/charts/vault-0.28.1.tgz b/hashicorp-vault/charts/vault-0.28.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..ef0f05f52e28759a71fd4a2f08aa88d239748ec8 GIT binary patch literal 49807 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 z z=6PCYvB=>SvLfCNZh1myn6E^xtUrixd)jJborC2=F`tC0K&>TG2F$4TvHHSH(K1ue z4EcrGn*BZEk1bFHeEiJ{IR`3uM_)=YO^_zu_f$o49cKcdRt#^EXgDhlXH3yI9I)mM zP+aQzspHABfOEjbwU7;E(V6%jcu-DwhD71XHg-Ye4z9va>P*PB`1KwerNUH4Orw4q zLuZsACeg#pSBB^jM!v*p&|8s_x(@187z15-DRxZgGQW9FN23OpI8nRcn-#i&vZCct zf`9IEz;!ENtwbA8fjm65RTX>;3sYhleNF30$c;j+h(uXOAJW$GueM+-htEvBfjaRY zRM*6NA-Ve4T?edvM4q~=f~IC%>n2{P>nOVj!o=8kFA5RnT@}ACUor{tdp#x~tHAt` zvNLUar%tpvOLy44Evf?pSf=_K8wBUu`SC~`L?%ONL;*L@`W*rqCe@-d&M-qQmfXBkN>BYe|e>fu)RDtPs@FovMrT1vcfL*YICe37)zvu*(+m2D?2F$t@dLQUeGu#KPc%6#}}J5 zO_}KTBG|x?t0gr}Z zwy$F(T{M99At#b`+M|Dw$H<}(7zVs;)J*zb+D*by#wb3%4ap}iA0q9E^7JkV;Q^o_ z%|ZQQ(4wg&&@HG&T@g)i5 zbnUC-G+Cubu^NS!!Ka`rmk{G|`=b$ZzQEV6=*c+3Bupi&sHao`l5&)Zzv4DjrVTZk z#^Ef)dQCqX!5~fjJwU+#a13DBw7=rDx|&#cesb;506>&IZ#5f?y#M-N9TIehno0#} zyk7#Y5y(nG26!Wt$Z9?wN&S(w)EZY4HmIemsH;TTbM>~ zxrr)p2=~#RNFYjLZTb~2XkWJ(ox*UwcY5^0>kr4GHbMzMG3-?7vK^xaEoBd$4IiE8 zuI0o?@!9KzEM2*JV0da2ww~&f!%>W~g1JoK{YsrEkSTm1T7`w#i=z=Wp)#r;L_KB5 zl9uM+$d&<=W6qs&;R_T~ zV0Ld6c)zypOtG`-WZb35^H!^#wp^_-0bD!vX*Z`mZFlJ0%SKeImcsbAH^-9x=!jr@ z?HLo~FhRrCzIr_+r?~*1JX%2y7slXcO|>{y{3Ujs7RFwO2uR(v5-^ zy04Kl*wnfoa2jha`BsrdX%qw_+AQu!nf?L0oMPTFpt%T&^5-eG%}2`T`2of%sg?yb zT;jpN`$951u~?p**erhffnqZ)Z%2VsNiI(#0N7l{F{)ce3h9KC<1vbDLt9iP1akHh`5U2iafi};&SbIR{~$H#Au_V>QARNTYJso@7eppFbE=#X=yA?g;0@2$>fzrg^E9aff=@6Ff)TGo zf^iJbU%Ehte!|LFcf0o!x-`SdoSpCO?;oC?p8t6GpPIe4wY;}F8KL=wjP>P1&_=4F zfkfk=BY@iGa6gJNqU1Q0o&pYVz*;UoC`Bh(*~;NW&_=u&SjR!U`9<;4{~JmWe_6d? z1C4E%5r+XgbE%y3iqhCf*1kSEM(IFDdl$}`v+s}iL@c3y53k{^KWZ-LB$~lQ6>xkrhw79>7QeVlrqPI*I|EE8QJRmEi zDFt=|5pPQ&!X5|MXp#D3UcJO_BcpLbx^YgcJ3tT*K~C~hj;}%)Sua-!>~7AtTXo1H zF4_rVjsAkQ7v$}J5L$kuwg#l^kmMId@drN9Pj)a-%lI7~lc;*!vzkYvqfW5=T#-tm zE10dwEd)N$w~rBwFmK#}q2l-V;hq+1@kfejm^sG1gBbYrSie6ohQav2KSwa+A{g>V z^BlkM#l$Zhih5eP!jDWoZui!tf%x!Msb>QAKQfF)U^yfa+YuZ6K3cuMLoX=T^xq9J zS#D>IY~gFG>zjt_h!fjB&_Zb^i@R~O>z(Z%TZ6EkVRLgsBz0>M*bUiM8=sYj`K#Zp zS-E*miy^HFOUX6vR5qrIC_ecM0V| z3urhP+FmklUw*!LX3Ab;n-g&473REnt*lyOmZa!02 zsqB9p(7B0MkEeW7ZN@|gE1=Rdi1?sFu4^$7jSfX$fE)+RjWQ-sa&H`~r<5Fij@=oB z-5XZBp=dJ6nW7~@8LpgvFc}gY`_iHIGw1_li7Y=&Sq1I%a$+6LsX6UN&gH1gN^)4J zhruq^XbN?`MZ_&bl5yBBo^(|*9=X=hGvUku189DWJ78s&a&*v{(ox#8XH(9J7q)YX z&I4T7K>5?M{mk*KNR<>?{$CZZN)K7@bxnI&dPo)QRpNnD?prhcZbVtVu*)%?EbNC{ zbvXo_>ULxif1vBh9c$J7(AUFw*!OpTr~8~^e^i-r$W?g$pj#v>v4HK0vk_gjlBHUu zF1?s0W|c@;7cvc5bL18GR*V3QHF$U``^jS96q6I>R7ALwYa{W12XVmdK%~Xqr~i>_rPqpJq+BwmD4%!{BRqkHhHs>g#g+;xSM zfs99lS{;Zg#>Un5EdR@uTzCfe(B21^Wa=V|S#bp`s&oSGmrM(M5io&sFEUo%%BHrrRF!zqV9ZIf zthf+$c}nu(c%^V?Ov4jfyu<)*#twS1$co(s9HUB*!k4bry&5O9bZ4z$p!GOR8Hg_2 z`C+Duhl#X6rc!0OXObqjJJ8{#g2i6SXk5G#aIqmcw!oMdOID2YDq%j8FH0`iP$h#A zbqrBeVOiTNopDQPm0R^h1ltSSq38h|#T&~t9q)+Z&>~b}Mr zD`JYf-gUCLd>4x7>_^h({_7)#@Q@V;H@zT+~iXc+RAc1Jm5@4j_I}m z26dJto1G)Z!&RoM5n+ip!}yL;k;16Bx>NqCT2XWw{#^&%98Q>fA`ML1S;!iMKF8)0kaA(knHWDq}`NAU`2Qg z$D&ZRY}O-%u~KEwSNjr1Yy6t`IH370zWv-X;QSGOO+c0gZP=`+udp-r-Sv>9{e+<@ z?}y!D(axeSR*zAt8+uc&iB_GWocj3~`B8lLAZL=98TTFzyd~(c3?vGF!TT~z^t6qF9mjOw<y3jZ=e3=NTTEoc_6S1!w`CRCH1>2kK_ zy)mYKplkw2_Yc*lvP2!4#a3?CK z&M@|_#tBhy3R_&kZwMn;*^=1~gaAK`bH12`Fl{Op{Rv%xm2V0uQFtl%&v?wBj20RR z!Q^MOLdQ(mZzv5-8${nWN{vMJh#|r#aR4$*ERMClTV9VusD|io@P3&0qgOVZWMprT zjk}Puvis6$MyAlVCA?amN(Z;o!ihmV^*-)>cyo4saQN~3%Gw?T6QW)HrFEIfO4^S@Cxi4~Zf$nekJs+bh0F zl3a~5jj8?T&RlYA8HB(l%EZ6Zo)1_0d|acS#q;@^ddOIIYP196G^pd2j?0La#_L$T z*KkgjfXkpyCyLN&T_ef8gln8-o$wKOT~#Kivts2|SFQ41#*Wqe_5Pc-IwFwdQ9D=? zhD#2a8Py8{c-vPFmMKszn+^X~3ncTr?BK4GG*IWK9|F|D+T zay&#wdBlI597dIwmTW*vI)ypcrZ1K#Up8ZAx*YjGtcmhdoXZsFGR3!U&K&5X+*H(m z6-p5tVg@Id<8MoZ5A55}JC)$?TueFUI7}r{KzYn7t?3VOjA&&)ipM?g$G4{@*&7b{ z1AIeNiGx)Ah_!R%Grpo#h)OSN=dH=r5zr%Qj|n)aIHC0MCL_}i`^U5f)fyM-HLts) z?#&=I$3f0S?3F=(e=ClMEd<;a5`3#6rlx>HPz~Ad-);cgJ13-A7>Q4+b(7f5yUApf z#pjr)uA+G`(e3BD8(qBKf;k18fOja1A@|Y;Q-r@4cBT7sEw!9ekPEDHV=c9IA&>1` zc}A*-YA-uaZeQ;iGK-upXHV21D^!w6sT52grH118U74vHc!snhl{_-)E5$Lf7rCU; z2(e1Zm7+H2z&K{#V@f=krFtPY;SDOtoC+=ENyv4MOf6>A*Kng6$S$>s4;M=CtFs)D zBlU1hsj19rKdLeuL>g(tUU)^tTQc0IS|t3U?DHj}h{}mBfmn)#qGKI}g!oF}iRXU3 zr+eIA8}mXrdv6by+a<2g80==Hbl2_)+JjK0FCK+*qoTdOOv$t1Iw4ARf*LmgZvem#L+$LJ zO-2A8k$O2P3!yTi8Y%bYbdtO!#jY^eFRvI(L^IM`w5-cAtkF&ASOIfKS#0xji2M^J z>SX;q@*882gGyv*Dfn#5h4|75g%O-UgW{=+ixxQqu(cNJVgOqm-%_p!IsQn>lA!8x z*Fwp1L~6h;vQt!_{f!t7RrJ?4iowyHuN(v zqD5A;gc+T}j#e|Ivslu3nbOB$ODh=Dd$Fb#b84}e7Ke&&$vw0wJgPecvxetR(y*pg zI@)r5dP@0~(V*rh0H@|z3XPYZg~@+LVX`2lbqQk1Gk87 z|7kpndq&)At#58`bvFMnQlCB$J5fE~UkU!F7G#cAiCV zjZ4GT_2pJaY)M01X;SS+Mp1I1s$}p|;(vXWnTnL@D;hG`y#sw5y;!ood!%ZWrRHl) zn5<|A+V8_3JxtQxu=Xv@oRMI zo%Z@>d(Fw?qwZK2{v-j}RGahypTauaqp_4GGKn=L+KiH*OJUr-R89eICCOTtf2b$7 zY#htU8gwFc5NOwlA_~x2=O+-iXw>AIzmcjW=x{w>?SY(s3T=D!g>1Ja+ilT; zRZ2$1!Z`ri7I;wk{$Miz_HeE*5j-$|g-IT7jONf~tX?V)z*p~@tY>;KsrNeFkx53o zZwQ~f5*cMy5TA82tRX57Fq#=1nJZ)Tun@`IVEH&nSyLhCsfc2nG`TuI%Lo$|ag}-} znN3b*j?cpVuGHT1P1i=k%NuqK=e7rz=Zy)o;@xEm@K9fgH22qKm+O4Gq6G8N}7` zVQtoiVqiUDWQlFgJ+U$C_o{nm$ajK=~ zX>dT-sdmfHqohEtTOzllNUl@x&WdfWDtFf?FJGr3l|CFb#vyy1oh9h&%@V|&KXg67 zR3HMd<4L~8&4(jm;u;nS;}R5wH0KnoA&TgLv&~7o1+!IcB)c?@WI0;ViCT!dp(C>G z&favRnJn%Qo%d)U6;QK3ciV&u6j$=u2qvp2`82CILWYIJ~84qf4)l!Gz_%Rn;oAuHkFUIK! zBAjyZO%IE1Vvw#A*;EqJ^yLOLEjFC#NrIVVJ4eT55lv4V&&0q{9n9pe)rx3ZM7Yla zf_-L(`aFK1&+IUt7m>B2Q&LQw5ICr})iTLrI@{*E_RcGO#v7{}>wM<+I7i33bEhyF zhwA7WT3C463?|MB3LK*=LoY(V% z0Vb-=4E5IqC}lK-ma2w?A4Wc^2oQ6M@!&;S6$S%(tu(w&SE~kmArrS?)>c&`z1*La zm?f*h_o6mw>QEZJ7}-y>;)w?5ni!%_VEPlnYxfg%dE9#MnoDbOHC<*J)u^QDN+-iE zw8w0F_Q-iL&M3kI)7~PYpQ6*Khassb;MeNc=+SNlB&2V<={n{JjQ#_tdR_Tdp!;e4JO9 zkQzZ&fWzrlj40fSr@C%bNvUZ5C9nF|n&xWdi=Oebs$R@0rYH~9Rj~w3#@QuOzfwj* zeWN3Dqf|_QQKo#EQl{4?6^JurtAt|d4(bRI&!ZHiC#Uak_*+!O$jG;Tf_YL`32(ZV)TqNb99zx z=_Gq~NfzS;+}N}B@jNBa%Zi{+ z=Zl>>*{X)N`d$imqq9^)ICPhxDX=s}rY6sjsFK(Y=OU%F^SsUceH+@o>*gnwXE`-F zX}N{{k7#VX@B3J&0n&LYb66wkYCjaJj^>Jb*_E2wjq>7Tf4o{g&qcka74wLLO(5>pg?WyxVu`6BCT<;rJIib^TpS57}=%KyAHVVS|ON0rMt<0oe$#(Q&o7~M-0 zmmTH&rEaAmA{O0@>(g$oo>f<_b1kuX^G9{OVE6SG`n}PFCWSy-K?PTtB^bbR8RpD ztwq{kn|yj>4ogKxGZ<)}e1cCz7BL>ZN(j}#u#%%)ty1J}X?27ZL&kzJ;7s~JEUh`Q zBgM?}y2R{xg_&W=)mY0cWhJ@w3AH5QVm6_;kroXG?>`BGRaBy{$`>ewx2$etc~|5& zkG}4^7Ih9~-_;x;w_Z2q)6UB8R1i32Jd$(gcdxVU3e355E3Pso3^2#mI z;LMyf^9aS2uea~!tj~Y8Y27*1N%7Zi&ixgBaNgd1pNvbkCCpXcaMMHK&xyb#XG$wd zN}jwt>&24JwzT1zwT+~Eqn_>NjHC}9PZF#gFZl9V^iDdR_OQ-3w}jKmX~oU%CY5S$ zPvAMXmzF0T{xMbbV_`ok`MaZ@Kpp^39IUubQ3^FB~@#BkQEf6*?RApWn}QU$zDzkZ(m`T5V!e}4Y+^PkFpHrTl5fB*c? N=){|%&2WQ-0RUykeRBW+ literal 0 HcmV?d00001 diff --git a/hashicorp-vault/values.yaml b/hashicorp-vault/values.yaml index 691f7094..6029a2f0 100644 --- a/hashicorp-vault/values.yaml +++ b/hashicorp-vault/values.yaml @@ -48,4 +48,4 @@ vault: termination: "reencrypt" image: repository: "registry.connect.redhat.com/hashicorp/vault" - tag: "1.16.2-ubi" + tag: "1.17.2-ubi" diff --git a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml index 8156e2af..a17a6974 100644 --- a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml index 8156e2af..a17a6974 100644 --- a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml index 8156e2af..a17a6974 100644 --- a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-naked.expected.yaml b/tests/hashicorp-vault-naked.expected.yaml index 8727ef0e..c3950b6d 100644 --- a/tests/hashicorp-vault-naked.expected.yaml +++ b/tests/hashicorp-vault-naked.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-normal.expected.yaml b/tests/hashicorp-vault-normal.expected.yaml index 8156e2af..a17a6974 100644 --- a/tests/hashicorp-vault-normal.expected.yaml +++ b/tests/hashicorp-vault-normal.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR From 0b45eeada9359aeb447301799206859228dc4f2f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 15 Jul 2024 11:20:54 -0600 Subject: [PATCH 124/222] Update ESO to 0.9.20 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.9.19.tgz | Bin 76457 -> 0 bytes .../charts/external-secrets-0.9.20.tgz | Bin 0 -> 81759 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 505 ++++++++++++++++-- ...-secrets-industrial-edge-hub.expected.yaml | 505 ++++++++++++++++-- ...ecrets-medical-diagnosis-hub.expected.yaml | 505 ++++++++++++++++-- ...olang-external-secrets-naked.expected.yaml | 505 ++++++++++++++++-- ...lang-external-secrets-normal.expected.yaml | 505 ++++++++++++++++-- 9 files changed, 2279 insertions(+), 254 deletions(-) delete mode 100644 golang-external-secrets/charts/external-secrets-0.9.19.tgz create mode 100644 golang-external-secrets/charts/external-secrets-0.9.20.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index b304d092..802979b4 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.1.0 dependencies: - name: external-secrets - version: "0.9.19" + version: "0.9.20" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.9.19.tgz b/golang-external-secrets/charts/external-secrets-0.9.19.tgz deleted file mode 100644 index 66fffaa0b08d686867fc9e4307204eaae1e22964..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76457 zcmV)gK%~DPiwFP!000001ML0#cH2glFpBrzehM6BX4(0EB565})1TMLH={^STJ4*b zq}Zp|tXXl9ghWIjzyUzXN;;2qUf?|0Z|_|f6z)|dNYS0bn(0_Xp)R|s_Wk02&io`| z;V|{5iJzt8zx4k+h3C6(zs3I^e)sKD{lD`0%i;4E-#mTs^y#w5o%K7M)skLN7OM)zzH_BIA?@Qdfq8~6Xar-!)z&%S%{ z;+yZD;{LxleERG!-qYS@(DMAr_n$3;4}OvcarDx=efEegm-(MhNB?_t_`e^`{B)WG z%Zz?}CC-b-&x^NU5xe#mew2AvapJvRP2jbk`RSv1yzpOo^DJAYFURBSAe*lyqiMVt zSB_lyheyE_hmxNr>~6$AU!{HmuQC|Ttf%pU1<{zLDZNbNVHjV-|FGoRA1$NnM>qcc zU7XC)myd?tjhgzfGNGX-|Anm-gdYE&@4Z6+(dg;$>ElN@RtEnMZ?Qig{tjPyH+~of z(PGMOSC{_@quDEpjkIz|`%e{uMtg#W*Lad_zP|1O^L{(Ezl zdK2G|yqUiY<9mPRrK{=GPt&Va7~Xq9M2IV0vZ?R={<|lSi#I6uG*ayb-pKpokN@k@ zqtnO(Z0jdp7Q-0V(AO#rqH9G|F8G%R-hI6C?t(D%A|ECItpS01tEI<0-sB>S6aNv= zo8u7n&rh^py#(<5DuLNOL4xFeW-vkjz?(=kM-`p9zA;W7CQ(c z_;5kk)`S1c=Ds%zuCDw9i5w#2)Qhk5FH?_2GjAT>;Y@)(T?N-G=m$PrJeslymI}0S z1x;YVFg5QdB4#fUd?U_o{S9a(fM`=>-oyTD_x~3-?@ORIqineuFW7$n51&7O{$26@ zKYRMEyZ^g+e*b;^zaG8%yu=fXCmk;>9&h~jl+Na(|22k_`TOrfzzA2s-89_vfj7*X z;pLKN`yKW;`oO}K&s)9+7A6U1zV}ZrOIFd;d+`nZGgw@#uC9X5-e5TJL|;Bk3;y|t zrg@C_*N59HN8l*we^x9Et^z<5z$eiHMvp%Fyl-ls;Rv`G#B5UrT%?!ch0B>$zHI0t zoWW&=yBh|JAmgYfn+K`)1keY94z3hXG0pvL8&i3sQEdo|0h3vCwy;m>Ib)k_V@rd6<|yP z&;sBS4D&{uilTg!8eSwpGHdo(y=~g)#s)gT3J~Ix>{z+DciMqQY#{^@Jj`^c#SP)D zLN@V3lY>po^VODjQ$J|@-$M9;olF3Z{Q7n8Q7zfc(H(vXsRZg!yEFs0x4LG z()pOCPn0}}rr~PVvcwUeL`%aIHf9P8#TzluNV`X3^+!rR$9I75M!DEJ3gWSn4s+f@ z`{bX1E90!Z-_>5YP(K?^?s-S@#9a8vZIGXrJK$r~*_#qH`P9Wqv-lru5$4ONJzvcL zAKv+sc^uzt9q?)(w*j?q87_RdPSfHISRbG@%jNyQ^akR?!A_Pp^^Y&GS2n6Rs%*LGLl;=OJoj%tcwjNQ=J2osI*t3j9Q@^

e9?vX&2{P`z*yEQ@&1J8iL1Z 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 Ls1SjK0N4Zo6jePG literal 0 HcmV?d00001 diff --git a/hashicorp-vault/values.yaml b/hashicorp-vault/values.yaml index cb1b769f..fa73a060 100644 --- a/hashicorp-vault/values.yaml +++ b/hashicorp-vault/values.yaml @@ -48,4 +48,4 @@ vault: termination: "reencrypt" image: repository: "registry.connect.redhat.com/hashicorp/vault" - tag: "1.15.6-ubi" + tag: "1.16.1-ubi" diff --git a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml index 0f2218b0..74212ee2 100644 --- a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,12 +18,13 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm data: extraconfig-from-values.hcl: |- + disable_mlock = true ui = true listener "tcp" { @@ -42,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -63,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -95,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -126,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -167,10 +168,11 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server + annotations: spec: affinity: @@ -204,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -346,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -373,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml index 0f2218b0..74212ee2 100644 --- a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,12 +18,13 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm data: extraconfig-from-values.hcl: |- + disable_mlock = true ui = true listener "tcp" { @@ -42,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -63,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -95,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -126,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -167,10 +168,11 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server + annotations: spec: affinity: @@ -204,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -346,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -373,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml index 0f2218b0..74212ee2 100644 --- a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,12 +18,13 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm data: extraconfig-from-values.hcl: |- + disable_mlock = true ui = true listener "tcp" { @@ -42,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -63,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -95,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -126,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -167,10 +168,11 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server + annotations: spec: affinity: @@ -204,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -346,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -373,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-naked.expected.yaml b/tests/hashicorp-vault-naked.expected.yaml index 68b5a897..1fe2cd90 100644 --- a/tests/hashicorp-vault-naked.expected.yaml +++ b/tests/hashicorp-vault-naked.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,12 +18,13 @@ metadata: name: hashicorp-vault-config namespace: default labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm data: extraconfig-from-values.hcl: |- + disable_mlock = true ui = true listener "tcp" { @@ -42,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -63,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: default labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -95,7 +96,7 @@ metadata: name: hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -126,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: default labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -167,10 +168,11 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server + annotations: spec: affinity: @@ -204,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -346,7 +348,7 @@ metadata: name: hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -373,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-normal.expected.yaml b/tests/hashicorp-vault-normal.expected.yaml index 0f2218b0..74212ee2 100644 --- a/tests/hashicorp-vault-normal.expected.yaml +++ b/tests/hashicorp-vault-normal.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,12 +18,13 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm data: extraconfig-from-values.hcl: |- + disable_mlock = true ui = true listener "tcp" { @@ -42,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -63,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -95,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -126,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -167,10 +168,11 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server + annotations: spec: affinity: @@ -204,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -346,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.27.0 + helm.sh/chart: vault-0.28.0 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -373,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.15.6-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR From dd6be56971f161e47bec55f5aeb5863eac9873be Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 22 Apr 2024 16:19:43 +0200 Subject: [PATCH 046/222] Use --recurse-submodules when cloning In case a git repo has some things split over submodules, let's clone those too. The version of git in the imperative image is currently: sh-5.1# git version git version 2.39.3 Tested with: sh-5.1# git clone --recurse-submodules --single-branch --branch main --depth 1 -- "https://github.com/validatedpatterns/multicloud-gitops" /tmp/ Cloning into '/tmp'... remote: Enumerating objects: 426, done. remote: Counting objects: 100% (426/426), done. remote: Compressing objects: 100% (343/343), done. remote: Total 426 (delta 87), reused 221 (delta 40), pack-reused 0 Receiving objects: 100% (426/426), 545.98 KiB | 1.78 MiB/s, done. Resolving deltas: 100% (87/87), done. Co-Authored-By: Sergio Garcia Martinez --- clustergroup/templates/imperative/_helpers.tpl | 4 ++-- tests/clustergroup-industrial-edge-factory.expected.yaml | 2 +- tests/clustergroup-industrial-edge-hub.expected.yaml | 4 ++-- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 4 ++-- tests/clustergroup-naked.expected.yaml | 2 +- tests/clustergroup-normal.expected.yaml | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index f28b5668..d55220e4 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -65,7 +65,7 @@ OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; {{- end }} @@ -109,7 +109,7 @@ OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; {{- end }} {{/* Final done container */}} diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 84d4eaa6..f34b5f18 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -408,7 +408,7 @@ spec: OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index d8158428..6641ff73 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -569,7 +569,7 @@ spec: OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -668,7 +668,7 @@ spec: OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 4449986d..a61ce547 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -496,7 +496,7 @@ spec: OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -595,7 +595,7 @@ spec: OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 13e66fc8..fdaf4293 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -261,7 +261,7 @@ spec: OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 0cb1cc33..93f6892a 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -458,7 +458,7 @@ spec: OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -557,7 +557,7 @@ spec: OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; mkdir /git/{repo,home}; - git clone --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest From 60600dc8b27b64f14040af3a2ee4ed191f83229d Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 22 Apr 2024 17:55:34 +0200 Subject: [PATCH 047/222] Drop support for IIB on OCP 4.12 The last job we ran with that for IIB was more than 4 months ago. --- ansible/roles/iib_ci/README.md | 11 ----- ansible/roles/iib_ci/defaults/main.yml | 4 -- ansible/roles/iib_ci/tasks/main.yml | 12 ++--- .../iib_ci/tasks/mirror-related-images.yml | 18 -------- .../iib_ci/tasks/setup-external-registry.yml | 45 ------------------- 5 files changed, 6 insertions(+), 84 deletions(-) delete mode 100644 ansible/roles/iib_ci/tasks/setup-external-registry.yml diff --git a/ansible/roles/iib_ci/README.md b/ansible/roles/iib_ci/README.md index 98355ad9..251123f8 100644 --- a/ansible/roles/iib_ci/README.md +++ b/ansible/roles/iib_ci/README.md @@ -64,17 +64,6 @@ use that. Run `make iib` with the following environment variables set: * `INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:492329` * `KUBEADMINPASS="11111-22222-33333-44444"` -### OCP 4.12 and previous versions - -Due to the lack of v2 manifest support on the internal registry, we use an external -registry. Run `make iib` with the following environment variables set: - -* `INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:492329` -* `REGISTRY=quay.io/rhn_support_mbaldess/iib` -* `REGISTRY_TOKEN=:` - -*Note*: For the REGISTRY_TOKEN go to your quay repository, add a robot with "Write" permissions. The robot created will have a "username" and "password" fields. Set the REGISTRY_TOKEN environment variable to that value. - ## Useful commands * List IIBs for an operator: diff --git a/ansible/roles/iib_ci/defaults/main.yml b/ansible/roles/iib_ci/defaults/main.yml index 7605dba5..9873e072 100644 --- a/ansible/roles/iib_ci/defaults/main.yml +++ b/ansible/roles/iib_ci/defaults/main.yml @@ -1,10 +1,6 @@ rh_internal_registry: registry-proxy.engineering.redhat.com iib_image: "{{ lookup('env', 'INDEX_IMAGE') }}" -external_registry: "{{ lookup('env', 'REGISTRY') }}" -external_registry_token: "{{ lookup('env', 'REGISTRY_TOKEN') }}" -external_registry_email: noemail@localhost - kubeadminpass: "{{ lookup('env', 'KUBEADMINPASS') }}" internal_registry_ns: openshift-marketplace diff --git a/ansible/roles/iib_ci/tasks/main.yml b/ansible/roles/iib_ci/tasks/main.yml index ba6eb7c8..bb50f286 100644 --- a/ansible/roles/iib_ci/tasks/main.yml +++ b/ansible/roles/iib_ci/tasks/main.yml @@ -21,15 +21,15 @@ - name: Is OCP pre OCP 4.13? (aka registry supports v2 manifests) ansible.builtin.set_fact: - use_internal_registry: "{{ oc_version_raw.stdout is version('4.13', '>=') }}" + ocp_413: "{{ oc_version_raw.stdout is version('4.13', '>=') }}" + +- name: Fail if OCP < 4.13 as we do not support it for IIB testing any longer + ansible.builtin.fail: + msg: "OCP versions < 4.13 are not support for IIB loading" + when: not ocp_413 - name: Set up internal registry (OCP >= 4.13) ansible.builtin.include_tasks: setup-internal-registry.yml - when: use_internal_registry - -- name: Set up external registry (OCP < 4.13) - ansible.builtin.include_tasks: setup-external-registry.yml - when: not use_internal_registry - name: Install new IIB in cluster ansible.builtin.include_tasks: install-iib-in-cluster.yml diff --git a/ansible/roles/iib_ci/tasks/mirror-related-images.yml b/ansible/roles/iib_ci/tasks/mirror-related-images.yml index 32a36c07..bf7356d2 100644 --- a/ansible/roles/iib_ci/tasks/mirror-related-images.yml +++ b/ansible/roles/iib_ci/tasks/mirror-related-images.yml @@ -91,16 +91,6 @@ 'mirrordest_nosha': (mirror_dest + item | basename) | regex_replace('@.*$', ''), 'mirrordest_tag': 'tag-' + item | basename | regex_replace('^.*@sha256:', '')}}, recursive=true) }}" loop: "{{ all_images }}" - when: use_internal_registry - -- name: Create dict with full image name+sha -> mirror destination (OCP < 4.13) - ansible.builtin.set_fact: - image_urls: "{{ image_urls | default({}) | combine({item: - {'mirrordest': mirror_dest + '@' + item | basename | regex_replace('^.*@', ''), - 'mirrordest_nosha': mirror_dest, - 'mirrordest_tag': 'tag-' + item | basename | regex_replace('^.*@sha256:', '')}}, recursive=true) }}" - loop: "{{ all_images }}" - when: not use_internal_registry - name: Create dict with full image name+sha -> image key without sha ansible.builtin.set_fact: @@ -124,14 +114,6 @@ src: ./templates/imageDigestMirror.yaml.j2 dest: "{{ iib_local_folder }}/imageMirror.yaml" mode: "0644" - when: use_internal_registry - -- name: Template out imageMirror.yaml (OCP < 4.13) - ansible.builtin.template: - src: ./templates/imageContentSourcePolicy.yaml.j2 - dest: "{{ iib_local_folder }}/imageMirror.yaml" - mode: "0644" - when: not use_internal_registry - name: Template out mirror.map ansible.builtin.template: diff --git a/ansible/roles/iib_ci/tasks/setup-external-registry.yml b/ansible/roles/iib_ci/tasks/setup-external-registry.yml deleted file mode 100644 index a9a9b10a..00000000 --- a/ansible/roles/iib_ci/tasks/setup-external-registry.yml +++ /dev/null @@ -1,45 +0,0 @@ -- name: Check that we can push to the external registry - ansible.builtin.fail: - msg: "REGISTRY: '{{ external_registry }}' and REGISTRY_TOKEN: '{{ external_registry_token }}'. Both need to be set" - failed_when: > - (external_registry is not defined or external_registry | length == 0) or - (external_registry_token is not defined or external_registry_token | length == 0) - -- name: Get current cluster pull secrets - ansible.builtin.command: - oc extract secret/pull-secret -n openshift-config --to=- - register: pull_secrets_raw - -- name: Add external registry to pull secrets and set auth fact - ansible.builtin.set_fact: - pull_secrets_new: "{{ pull_secrets_raw.stdout | from_json }}" - external_registry_auth: "{{ external_registry_token | b64encode }}" - -- name: Add local registry to pull secrets - ansible.builtin.set_fact: - pull_secrets: "{{ pull_secrets_new | combine({'auths': {external_registry.split('/')[0]: {'email': external_registry_email, 'auth': external_registry_auth}}}, recursive=true) }}" - -- name: Get a tempfile for the pull secrets - ansible.builtin.tempfile: - state: directory - register: pull_secrets_tempfolder - -- name: Store pull secrets in tempfile - ansible.builtin.copy: - dest: "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" - content: "{{ pull_secrets | to_nice_json }}" - mode: "0644" - -# We cannot store the logins back in the cluster, because quay.io would be overwritten and not have -# access to the images openshift needs. See: -# https://github.com/moby/moby/issues/37569 -# - name: Update pull-secret in the cluster -# ansible.builtin.shell: | -# oc set data secret/pull-secret -n openshift-config --from-file="{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" -- name: Set Mirror URL fact for external mirror IIB - ansible.builtin.set_fact: - mirror_iib: "{{ external_registry }}" - -- name: Set Mirror URL fact for external mirror - ansible.builtin.set_fact: - mirror_dest: "{{ external_registry }}" From f50deb9c11090b2dffbb6da07431eb560cda671b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 22 Apr 2024 18:08:17 +0200 Subject: [PATCH 048/222] Stop saving stderr in a file when running skopeo --- ansible/roles/iib_ci/tasks/mirror-related-images.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ansible/roles/iib_ci/tasks/mirror-related-images.yml b/ansible/roles/iib_ci/tasks/mirror-related-images.yml index bf7356d2..16b386ff 100644 --- a/ansible/roles/iib_ci/tasks/mirror-related-images.yml +++ b/ansible/roles/iib_ci/tasks/mirror-related-images.yml @@ -33,9 +33,9 @@ right=$(grep "{{ image }}" "{{ iib_local_folder }}/mapping.txt" | cut -f2 -d=) right_base=$(echo $right | sed -e 's/:.*$//' -e 's/@.*$//') right_log=$(echo "${right_base}@${left_sha}" | sed -e 's/\//-/g') - if skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"{{ image }}" &> /tmp/skopeo-"{{ image | regex_replace('/', '-') }}".log; then + if skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"{{ image }}" > /tmp/skopeo-"{{ image | regex_replace('/', '-') }}".log; then echo "{{ image }}" - elif skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"${right_base}@${left_sha}" &> "/tmp/skopeo-${right_log}.log"; then + elif skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"${right_base}@${left_sha}" > "/tmp/skopeo-${right_log}.log"; then echo "${right_base}@${left_sha}" else echo "ERROR: both {{ image }} and echo ${right_base}@${left_sha} could not be found" From 5702167854b652b95f917b53a12d5aa858932650 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 22 Apr 2024 18:36:29 +0200 Subject: [PATCH 049/222] Rearchitect the code so we can print out the actual error --- .../iib_ci/tasks/mirror-related-images.yml | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/ansible/roles/iib_ci/tasks/mirror-related-images.yml b/ansible/roles/iib_ci/tasks/mirror-related-images.yml index 16b386ff..f502197a 100644 --- a/ansible/roles/iib_ci/tasks/mirror-related-images.yml +++ b/ansible/roles/iib_ci/tasks/mirror-related-images.yml @@ -33,13 +33,24 @@ right=$(grep "{{ image }}" "{{ iib_local_folder }}/mapping.txt" | cut -f2 -d=) right_base=$(echo $right | sed -e 's/:.*$//' -e 's/@.*$//') right_log=$(echo "${right_base}@${left_sha}" | sed -e 's/\//-/g') - if skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"{{ image }}" > /tmp/skopeo-"{{ image | regex_replace('/', '-') }}".log; then + left_out=$(skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"{{ image }}" 2>&1) + left_ret=$? + if [ $left_ret -eq 0 ]; then echo "{{ image }}" - elif skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"${right_base}@${left_sha}" > "/tmp/skopeo-${right_log}.log"; then - echo "${right_base}@${left_sha}" else - echo "ERROR: both {{ image }} and echo ${right_base}@${left_sha} could not be found" - exit 1 + echo "${left_out}" > /tmp/skopeo-"{{ image | regex_replace('/', '-') }}".log + right_out=$(skopeo inspect --authfile "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" --no-tags docker://"${right_base}@${left_sha}" 2>&1) + right_ret=$? + if [ $right_ret -eq 0 ]; then + echo "${right_base}@${left_sha}" + else # both left_ret and right_ret were != 0 + echo "${right_out}" > "/tmp/skopeo-${right_log}.log" + echo "ERROR: both {{ image }} and echo ${right_base}@${left_sha} could not be found" + echo "Printing both outputs:" + echo "Left out: ${left_out}" + echo "Right out: ${right_out}" + exit 1 + fi fi register: all_existing_images with_items: "{{ all_images }}" From 109027c4330d1e59032cc8042f88e3d22077a2cc Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 22 Apr 2024 20:55:18 +0200 Subject: [PATCH 050/222] Check for prereqs for IIB --- ansible/roles/iib_ci/tasks/main.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ansible/roles/iib_ci/tasks/main.yml b/ansible/roles/iib_ci/tasks/main.yml index bb50f286..6500b135 100644 --- a/ansible/roles/iib_ci/tasks/main.yml +++ b/ansible/roles/iib_ci/tasks/main.yml @@ -4,6 +4,14 @@ failed_when: (iib_image is not defined or iib_image | length == 0) +- name: Check for pre-requisite binaries presence + ansible.builtin.shell: | + which "{{ item }}" + with_items: + - skopeo + - oc + - podman + - name: Set IIB fact ansible.builtin.set_fact: iib: "{{ iib_image.split(':')[1] }}" From a073b8c4c8101c42cc7f8c52b81b3c2a5324a667 Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 23 Apr 2024 17:07:47 -0400 Subject: [PATCH 051/222] chore: added annotations controling gitops and fail for missing meta for clusterdeployments Signed-off-by: Tomer Figenblat --- acm/templates/provision/clusterdeployment.yaml | 12 ++++++++++++ tests/acm-normal.expected.yaml | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/acm/templates/provision/clusterdeployment.yaml b/acm/templates/provision/clusterdeployment.yaml index cc37c161..f7f71a52 100644 --- a/acm/templates/provision/clusterdeployment.yaml +++ b/acm/templates/provision/clusterdeployment.yaml @@ -3,6 +3,14 @@ {{- range $group.clusterDeployments}} {{ $cluster := . }} + +{{- if (eq $cluster.name nil) }} +{{- fail (printf "managedClusterGroup clusterDeployment cluster name is empty: %s" $cluster) }} +{{- end }} +{{- if (eq $group.name nil) }} +{{- fail (printf "managedClusterGroup clusterDeployment group name is empty: %s" $cluster) }} +{{- end }} + {{- $deploymentName := print $cluster.name "-" $group.name }} {{- $cloud := "None" }} @@ -30,6 +38,8 @@ metadata: namespace: {{ $deploymentName }} labels: vendor: OpenShift + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: baseDomain: {{ $cluster.baseDomain }} clusterName: {{ $deploymentName }} @@ -65,6 +75,8 @@ metadata: {{- end }} {{- end }} name: {{ $deploymentName }} + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: hubAcceptsClient: true {{- end }}{{- /* range $group.clusterDeployments */}} diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 1e63d2e7..b3627634 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -101,6 +101,8 @@ metadata: namespace: aws-cd-one-w-pool-acm-provision-edge labels: vendor: OpenShift + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: baseDomain: blueprints.rhecoeng.com clusterName: aws-cd-one-w-pool-acm-provision-edge @@ -128,6 +130,8 @@ metadata: namespace: aws-cd-two-wo-pool-acm-provision-on-deploy labels: vendor: OpenShift + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: baseDomain: blueprints.rhecoeng.com clusterName: aws-cd-two-wo-pool-acm-provision-on-deploy @@ -719,6 +723,8 @@ metadata: cluster.open-cluster-management.io/clusterset: acm-provision-edge clusterGroup: region name: aws-cd-one-w-pool-acm-provision-edge + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: hubAcceptsClient: true --- @@ -730,6 +736,8 @@ metadata: cluster.open-cluster-management.io/clusterset: acm-provision-on-deploy clusterGroup: acm-provision-on-deploy name: aws-cd-two-wo-pool-acm-provision-on-deploy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: hubAcceptsClient: true --- From c6ffd0ecdab72ff98f3cf89271ab4c5433c9f5bf Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Fri, 26 Apr 2024 11:05:33 -0400 Subject: [PATCH 052/222] chore: removed managedclusterset spec Signed-off-by: Tomer Figenblat --- acm/templates/provision/managedclusterset.yaml | 3 --- tests/acm-normal.expected.yaml | 6 ------ 2 files changed, 9 deletions(-) diff --git a/acm/templates/provision/managedclusterset.yaml b/acm/templates/provision/managedclusterset.yaml index dce01f73..2c8eaffa 100644 --- a/acm/templates/provision/managedclusterset.yaml +++ b/acm/templates/provision/managedclusterset.yaml @@ -8,9 +8,6 @@ metadata: cluster.open-cluster-management.io/submariner-broker-ns: {{ .name }}-broker argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true name: {{ .name }} -spec: - clusterSelector: - selectorType: LegacyClusterSetLabel {{- end }}{{- /* if .clusterPools) */}} {{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index b3627634..3e6fbc74 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -749,9 +749,6 @@ metadata: cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-edge-broker argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true name: acm-provision-edge -spec: - clusterSelector: - selectorType: LegacyClusterSetLabel --- # Source: acm/templates/provision/managedclusterset.yaml apiVersion: cluster.open-cluster-management.io/v1beta2 @@ -761,9 +758,6 @@ metadata: cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-on-deploy-broker argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true name: acm-provision-on-deploy -spec: - clusterSelector: - selectorType: LegacyClusterSetLabel --- # Source: acm/templates/multiclusterhub.yaml apiVersion: operator.open-cluster-management.io/v1 From 04951900f44864adafac72c18f1506a608d5edb3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 30 Apr 2024 11:23:43 +0200 Subject: [PATCH 053/222] Rework IIB loading support This adds multiple IIB support in order to cater for the ACM IIB case, where the MCE operator might be in another IIB completely. To load multiple IIB for different operators, one needs to set the env variables as follows: export OPERATOR=advanced-cluster-management,multicluster-engine export INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:713808,registry-proxy.engineering.redhat.com/rh-osbs/iib:718034 It is implied that the first IIB is for the first operator in the list, and the second one for the latter. Tested gitops-iib and it all worked with no changes. --- Makefile | 4 +- ansible/roles/iib_ci/README.md | 8 ---- ansible/roles/iib_ci/defaults/main.yml | 2 +- .../iib_ci/tasks/fetch-operator-images.yml | 20 ++++---- .../iib_ci/tasks/install-iib-in-cluster.yml | 10 ++-- ansible/roles/iib_ci/tasks/main.yml | 48 ++++++++++++++----- .../iib_ci/tasks/mirror-related-images.yml | 10 ++-- .../iib_ci/templates/catalogSource.yaml.j2 | 6 +-- .../templates/imageDigestMirror.yaml.j2 | 12 ++--- 9 files changed, 69 insertions(+), 51 deletions(-) diff --git a/Makefile b/Makefile index 7882a9ce..86cb5177 100644 --- a/Makefile +++ b/Makefile @@ -113,9 +113,7 @@ secrets-backend-none: ## Edits values files to remove secrets manager + ESO .PHONY: load-iib load-iib: ## CI target to install Index Image Bundles @set -e; if [ x$(INDEX_IMAGES) != x ]; then \ - for IIB in $(shell echo $(INDEX_IMAGES) | tr ',' '\n'); do \ - INDEX_IMAGE="$${IIB}" ansible-playbook common/ansible/playbooks/iib-ci/iib-ci.yaml; \ - done; \ + ansible-playbook common/ansible/playbooks/iib-ci/iib-ci.yaml; \ else \ echo "No INDEX_IMAGES defined. Bailing out"; \ exit 1; \ diff --git a/ansible/roles/iib_ci/README.md b/ansible/roles/iib_ci/README.md index 251123f8..6afccb1a 100644 --- a/ansible/roles/iib_ci/README.md +++ b/ansible/roles/iib_ci/README.md @@ -56,14 +56,6 @@ make EXTRA_HELM_OPTS="--set main.extraParameters[0].name=clusterGroup.subscripti *Note*: In this case `acm` is the name of the subscription in `values-hub.yaml` -### OCP 4.13 and onwards - -Since 4.13 supports an internal registry that can cope with v2 docker manifests, we -use that. Run `make iib` with the following environment variables set: - -* `INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:492329` -* `KUBEADMINPASS="11111-22222-33333-44444"` - ## Useful commands * List IIBs for an operator: diff --git a/ansible/roles/iib_ci/defaults/main.yml b/ansible/roles/iib_ci/defaults/main.yml index 9873e072..397be608 100644 --- a/ansible/roles/iib_ci/defaults/main.yml +++ b/ansible/roles/iib_ci/defaults/main.yml @@ -1,5 +1,5 @@ rh_internal_registry: registry-proxy.engineering.redhat.com -iib_image: "{{ lookup('env', 'INDEX_IMAGE') }}" +iib_images: "{{ lookup('env', 'INDEX_IMAGES') }}" kubeadminpass: "{{ lookup('env', 'KUBEADMINPASS') }}" diff --git a/ansible/roles/iib_ci/tasks/fetch-operator-images.yml b/ansible/roles/iib_ci/tasks/fetch-operator-images.yml index 11df26cc..391f2ac2 100644 --- a/ansible/roles/iib_ci/tasks/fetch-operator-images.yml +++ b/ansible/roles/iib_ci/tasks/fetch-operator-images.yml @@ -2,9 +2,9 @@ # the operator name is defined in the variable "item". This # set of tasks is to be included in a loop that goes over the # needed operators -- name: Get default channel in the IIB for "{{ item }}" +- name: Get default channel in the IIB for "{{ item.key }}" ansible.builtin.shell: | - oc get -n "{{ internal_registry_ns }}" packagemanifests -l "catalog=iib-{{ iib }}" --field-selector "metadata.name={{ item }}" \ + oc get -n "{{ internal_registry_ns }}" packagemanifests -l "catalog=iib-{{ item.value['iib'] }}" --field-selector "metadata.name={{ item.key }}" \ -o jsonpath='{.items[0].status.defaultChannel}' register: default_channel_raw retries: 10 @@ -15,9 +15,13 @@ ansible.builtin.set_fact: default_channel: "{{ default_channel_raw.stdout }}" -- name: Get all related images in the IIB for "{{ item }}" +- name: Print default channel + ansible.builtin.debug: + msg: "Default channel for {{ item.key }}: {{ default_channel }}" + +- name: Get all related images in the IIB for "{{ item.key }}" ansible.builtin.shell: | - oc get packagemanifests -l "catalog=iib-{{ iib }}" --field-selector "metadata.name={{ item }}" \ + oc get packagemanifests -l "catalog=iib-{{ item.value['iib'] }}" --field-selector "metadata.name={{ item.key }}" \ -o jsonpath="{.items[0].status.channels[?(@.name==\"{{ default_channel }}\")].currentCSVDesc.relatedImages}" register: related_images_raw retries: 5 @@ -29,7 +33,7 @@ related_images: "{{ related_images_raw.stdout }}" # NOTE(bandini) -# The following code is here to fund out what the operator bundle image is and to make +# The following code is here to find out what the operator bundle image is and to make # sure it is on the internal registry. # This is all potentially hacky, but so far I could not find a single place in the cluster # where the olm.bundle image is available. The info is in there in the IIB, but it certainly @@ -37,7 +41,7 @@ # alpha commands inside the IIB image locally - name: Pull the IIB locally ansible.builtin.command: - podman pull "{{ iib_image }}" + podman pull "{{ item.value['iib_image'] }}" # $ opm alpha list channels /configs advanced-cluster-management # PACKAGE CHANNEL HEAD @@ -46,7 +50,7 @@ - name: Read the operator bundle from the default channel ansible.builtin.shell: | set -o pipefail - podman run -it --rm "{{ iib_image }}" alpha list channels /configs "{{ item }}" | grep -E "(\s){{ default_channel }}(\s)" | awk '{ print $3 }' + podman run -it --rm "{{ item.value['iib_image'] }}" alpha list channels /configs "{{ item.key }}" | grep -E "(\s){{ default_channel }}(\s)" | awk '{ print $3 }' register: bundle_channel_raw - name: Set bundle fact @@ -70,7 +74,7 @@ - name: Get bundle image ansible.builtin.shell: | set -o pipefail - podman run -it --rm "{{ iib_image }}" alpha list bundles /configs "{{ item }}" | grep -e "{{ default_channel }}\s\+{{ bundle_channel }}" | awk '{ print $NF }' + podman run -it --rm "{{ item.value['iib_image'] }}" alpha list bundles /configs "{{ item.key }}" | grep -e "{{ default_channel }}\s\+{{ bundle_channel }}" | awk '{ print $NF }' register: bundle_image_raw - name: Set bundle image fact diff --git a/ansible/roles/iib_ci/tasks/install-iib-in-cluster.yml b/ansible/roles/iib_ci/tasks/install-iib-in-cluster.yml index 4b39184c..76a649b2 100644 --- a/ansible/roles/iib_ci/tasks/install-iib-in-cluster.yml +++ b/ansible/roles/iib_ci/tasks/install-iib-in-cluster.yml @@ -1,3 +1,7 @@ +- name: Set IIB local folder fact + ansible.builtin.set_fact: + iib_local_folder: "/tmp/manifest-{{ item.value['iib'] }}" + - name: Remove manifest folder "{{ iib_local_folder }}" ansible.builtin.file: path: "{{ iib_local_folder }}" @@ -16,14 +20,14 @@ - name: Mirror catalog manifests only to "{{ iib_local_folder }}" ansible.builtin.shell: | oc adm catalog mirror --insecure --manifests-only --to-manifests=. \ - "{{ iib_image }}" "{{ rh_internal_registry }}/rh-osbs" > catalog.log 2>&1 + "{{ item.value['iib_image'] }}" "{{ rh_internal_registry }}/rh-osbs" > catalog.log 2>&1 args: chdir: "{{ iib_local_folder }}" - name: Mirror IIB to "{{ mirror_iib }}" ansible.builtin.shell: | oc image mirror -a "{{ pull_secrets_tempfolder.path }}/.dockerconfigjson" \ - "{{ iib_image }}={{ mirror_iib }}" --insecure --keep-manifest-list 2>&1 + "{{ item.value['iib_image'] }}={{ mirror_iib }}" --insecure --keep-manifest-list 2>&1 args: chdir: "{{ iib_local_folder }}" register: oc_mirror_result @@ -43,7 +47,7 @@ - name: Wait for catalogsource to show up ansible.builtin.shell: | - oc get -n "{{ internal_registry_ns }}" packagemanifests -l "catalog=iib-{{ iib }}" --field-selector "metadata.name={{ operator }}" \ + oc get -n "{{ internal_registry_ns }}" packagemanifests -l "catalog=iib-{{ item.value['iib'] }}" --field-selector "metadata.name={{ item.key }}" \ -o jsonpath='{.items[0].status.defaultChannel}' register: oc_catalogsource_result retries: 30 diff --git a/ansible/roles/iib_ci/tasks/main.yml b/ansible/roles/iib_ci/tasks/main.yml index 6500b135..fcaad76a 100644 --- a/ansible/roles/iib_ci/tasks/main.yml +++ b/ansible/roles/iib_ci/tasks/main.yml @@ -1,9 +1,3 @@ -- name: Check that INDEX_IMAGE env variable is set - ansible.builtin.fail: - msg: "INDEX_IMAGE: '{{ iib_image }}' is not set" - failed_when: - (iib_image is not defined or iib_image | length == 0) - - name: Check for pre-requisite binaries presence ansible.builtin.shell: | which "{{ item }}" @@ -12,13 +6,11 @@ - oc - podman -- name: Set IIB fact - ansible.builtin.set_fact: - iib: "{{ iib_image.split(':')[1] }}" - -- name: Set IIB local folder fact - ansible.builtin.set_fact: - iib_local_folder: "/tmp/manifest-{{ iib }}" +- name: Check that INDEX_IMAGES env variable is set + ansible.builtin.fail: + msg: "INDEX_IMAGES: '{{ iib_images }}' is not set" + failed_when: + (iib_images is not defined or iib_images | length == 0) - name: Get cluster version # E.g. 4.13.0-rc.6 or 4.12.16 @@ -36,14 +28,44 @@ msg: "OCP versions < 4.13 are not support for IIB loading" when: not ocp_413 +- name: Set images array + ansible.builtin.set_fact: + iib_image_list: "{{ iib_images.split(',') }}" + +- name: Set operator array + ansible.builtin.set_fact: + operator_list: "{{ operator.split(',') }}" + +# Creates a dict like: +# "advanced-cluster-management": { +# "iib": "713808", +# "iib_image": "registry-proxy.engineering.redhat.com/rh-osbs/iib:713808" +# }, +# "multicluster-engine": { +# "iib": "713809", +# "iib_image": "registry-proxy.engineering.redhat.com/rh-osbs/iib:713809" +# } +- name: Set IIB dict + ansible.builtin.set_fact: + iib_dict: "{{ iib_dict | default({}) | combine({item.0: {'iib_image': item.1, 'iib': item.1.split(':')[-1]}}) }}" + with_together: + - "{{ operator_list }}" + - "{{ iib_image_list }}" + +- name: Working with the following IIB data + ansible.builtin.debug: + msg: "{{ iib_dict }}" + - name: Set up internal registry (OCP >= 4.13) ansible.builtin.include_tasks: setup-internal-registry.yml - name: Install new IIB in cluster ansible.builtin.include_tasks: install-iib-in-cluster.yml + with_items: "{{ iib_dict | dict2items }}" - name: Mirror all related images ansible.builtin.include_tasks: mirror-related-images.yml + with_items: "{{ iib_dict | dict2items }}" - name: Remove pullsecrets tempfolder ansible.builtin.file: diff --git a/ansible/roles/iib_ci/tasks/mirror-related-images.yml b/ansible/roles/iib_ci/tasks/mirror-related-images.yml index f502197a..74a0bc3b 100644 --- a/ansible/roles/iib_ci/tasks/mirror-related-images.yml +++ b/ansible/roles/iib_ci/tasks/mirror-related-images.yml @@ -1,8 +1,7 @@ -# This is needed because some operators like "advanced-cluster-management" -# install a second operator "multicluster-engine" -- name: Set operators list +# We redefine this var so it is easier to run this task independently +- name: Set IIB local folder fact ansible.builtin.set_fact: - operator_list: "{{ [operator] + (operator == 'advanced-cluster-management') | ternary(['multicluster-engine'], []) }}" + iib_local_folder: "/tmp/manifest-{{ item.value['iib'] }}" - name: Set all images to empty list ansible.builtin.set_fact: @@ -10,7 +9,6 @@ - name: Fetch operator images tasks ansible.builtin.include_tasks: fetch-operator-images.yml - loop: "{{ operator_list }}" - name: Print all_images ansible.builtin.debug: @@ -119,7 +117,7 @@ ansible.builtin.debug: msg: "{{ image_urls }}" -# OCP 4.13 uses the new fangled "ImageDigestMirrorSet", older OCPs use "ImageContentSourcePolicy" +# OCP 4.13 uses the new fangled "ImageDigestMirrorSet" - name: Template out imageMirror.yaml (OCP >= 4.13) ansible.builtin.template: src: ./templates/imageDigestMirror.yaml.j2 diff --git a/ansible/roles/iib_ci/templates/catalogSource.yaml.j2 b/ansible/roles/iib_ci/templates/catalogSource.yaml.j2 index 99087603..e7498892 100644 --- a/ansible/roles/iib_ci/templates/catalogSource.yaml.j2 +++ b/ansible/roles/iib_ci/templates/catalogSource.yaml.j2 @@ -1,9 +1,9 @@ apiVersion: operators.coreos.com/v1alpha1 kind: CatalogSource metadata: - name: iib-{{ iib }} + name: iib-{{ item.value['iib'] }} namespace: {{ internal_registry_ns }} spec: - image: {{ mirror_iib }}:{{ iib }} + image: {{ mirror_iib }}:{{ item.value['iib'] }} sourceType: grpc - displayName: IIB {{ iib }} + displayName: IIB {{ item.value['iib'] }} diff --git a/ansible/roles/iib_ci/templates/imageDigestMirror.yaml.j2 b/ansible/roles/iib_ci/templates/imageDigestMirror.yaml.j2 index 1b04f321..08a24735 100644 --- a/ansible/roles/iib_ci/templates/imageDigestMirror.yaml.j2 +++ b/ansible/roles/iib_ci/templates/imageDigestMirror.yaml.j2 @@ -3,16 +3,16 @@ kind: ImageDigestMirrorSet metadata: labels: operators.openshift.org/catalog: "true" - name: iib-{{ iib }} + name: iib-{{ item.value['iib'] }} spec: imageDigestMirrors: -{% for item in image_urls.values() %} +{% for data in image_urls.values() %} - mirrors: - - {{ item.mirrordest_nosha }} - source: {{ item.source_nosha }} + - {{ data.mirrordest_nosha }} + source: {{ data.source_nosha }} mirrorSourcePolicy: AllowContactingSource - mirrors: - - {{ item.mirrordest_nosha }} - source: {{ item.image_nosha }} + - {{ data.mirrordest_nosha }} + source: {{ data.image_nosha }} mirrorSourcePolicy: AllowContactingSource {% endfor %} From 00aae8c1ef4f8771003450eea8544537d9887769 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 30 Apr 2024 12:09:09 +0200 Subject: [PATCH 054/222] Switch to gitops-1.12 --- acm/templates/policies/ocp-gitops-policy.yaml | 2 +- acm/values.yaml | 2 +- operator-install/templates/pattern.yaml | 2 +- operator-install/values.yaml | 2 +- reference-output.yaml | 2 +- tests/acm-industrial-edge-factory.expected.yaml | 2 +- tests/acm-industrial-edge-hub.expected.yaml | 2 +- tests/acm-medical-diagnosis-hub.expected.yaml | 2 +- tests/acm-naked.expected.yaml | 2 +- tests/acm-normal.expected.yaml | 2 +- tests/operator-install-industrial-edge-factory.expected.yaml | 4 ++-- tests/operator-install-industrial-edge-hub.expected.yaml | 4 ++-- tests/operator-install-medical-diagnosis-hub.expected.yaml | 4 ++-- tests/operator-install-naked.expected.yaml | 4 ++-- tests/operator-install-normal.expected.yaml | 4 ++-- 15 files changed, 20 insertions(+), 20 deletions(-) diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index f46b30c6..bec5b343 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -45,7 +45,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: {{ default "gitops-1.11" .Values.main.gitops.channel }} + channel: {{ default "gitops-1.12" .Values.main.gitops.channel }} installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/acm/values.yaml b/acm/values.yaml index fb7cb03a..e9e5035b 100644 --- a/acm/values.yaml +++ b/acm/values.yaml @@ -1,6 +1,6 @@ main: gitops: - channel: "gitops-1.11" + channel: "gitops-1.12" global: extraValueFiles: [] diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index 8bf7761a..ca3234f8 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -13,7 +13,7 @@ spec: tokenSecretNamespace: {{ .Values.main.tokenSecretNamespace }} {{- end }} {{/* if and .Values.main.tokenSecret .Values.main.tokenSecretNamespace */}} gitOpsSpec: - operatorChannel: {{ default "gitops-1.11" .Values.main.gitops.channel }} + operatorChannel: {{ default "gitops-1.12" .Values.main.gitops.channel }} operatorSource: {{ default "redhat-operators" .Values.main.gitops.operatorSource }} multiSourceConfig: enabled: {{ .Values.main.multiSourceConfig.enabled }} diff --git a/operator-install/values.yaml b/operator-install/values.yaml index 28bc3d4b..8ce7fe67 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -7,7 +7,7 @@ main: revision: main gitops: - channel: "gitops-1.11" + channel: "gitops-1.12" operatorSource: redhat-operators multiSourceConfig: diff --git a/reference-output.yaml b/reference-output.yaml index cdc1a303..54f4052a 100644 --- a/reference-output.yaml +++ b/reference-output.yaml @@ -112,7 +112,7 @@ metadata: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: "" spec: - channel: gitops-1.11 + channel: gitops-1.12 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index 0291231a..9dfa7d79 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -109,7 +109,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.11 + channel: gitops-1.12 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 21a1c30d..453e8a9e 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -316,7 +316,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.11 + channel: gitops-1.12 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 40df35e2..8b50de7a 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -307,7 +307,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.11 + channel: gitops-1.12 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml index 4f0ac751..561fbd7b 100644 --- a/tests/acm-naked.expected.yaml +++ b/tests/acm-naked.expected.yaml @@ -110,7 +110,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.11 + channel: gitops-1.12 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 20a38d52..66f1c590 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -806,7 +806,7 @@ spec: labels: operators.coreos.com/openshift-gitops-operator.openshift-operators: '' spec: - channel: gitops-1.11 + channel: gitops-1.12 installPlanApproval: Automatic name: openshift-gitops-operator source: redhat-operators diff --git a/tests/operator-install-industrial-edge-factory.expected.yaml b/tests/operator-install-industrial-edge-factory.expected.yaml index 0ef51dc0..018eb4c5 100644 --- a/tests/operator-install-industrial-edge-factory.expected.yaml +++ b/tests/operator-install-industrial-edge-factory.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 + gitops.channel: gitops-1.12 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan @@ -26,7 +26,7 @@ spec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main gitOpsSpec: - operatorChannel: gitops-1.11 + operatorChannel: gitops-1.12 operatorSource: redhat-operators multiSourceConfig: enabled: false diff --git a/tests/operator-install-industrial-edge-hub.expected.yaml b/tests/operator-install-industrial-edge-hub.expected.yaml index 0ef51dc0..018eb4c5 100644 --- a/tests/operator-install-industrial-edge-hub.expected.yaml +++ b/tests/operator-install-industrial-edge-hub.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 + gitops.channel: gitops-1.12 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan @@ -26,7 +26,7 @@ spec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main gitOpsSpec: - operatorChannel: gitops-1.11 + operatorChannel: gitops-1.12 operatorSource: redhat-operators multiSourceConfig: enabled: false diff --git a/tests/operator-install-medical-diagnosis-hub.expected.yaml b/tests/operator-install-medical-diagnosis-hub.expected.yaml index 0ef51dc0..018eb4c5 100644 --- a/tests/operator-install-medical-diagnosis-hub.expected.yaml +++ b/tests/operator-install-medical-diagnosis-hub.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 + gitops.channel: gitops-1.12 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan @@ -26,7 +26,7 @@ spec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main gitOpsSpec: - operatorChannel: gitops-1.11 + operatorChannel: gitops-1.12 operatorSource: redhat-operators multiSourceConfig: enabled: false diff --git a/tests/operator-install-naked.expected.yaml b/tests/operator-install-naked.expected.yaml index 024ea7ea..fc0d7699 100644 --- a/tests/operator-install-naked.expected.yaml +++ b/tests/operator-install-naked.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 + gitops.channel: gitops-1.12 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan @@ -26,7 +26,7 @@ spec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main gitOpsSpec: - operatorChannel: gitops-1.11 + operatorChannel: gitops-1.12 operatorSource: redhat-operators multiSourceConfig: enabled: false diff --git a/tests/operator-install-normal.expected.yaml b/tests/operator-install-normal.expected.yaml index 0ef51dc0..018eb4c5 100644 --- a/tests/operator-install-normal.expected.yaml +++ b/tests/operator-install-normal.expected.yaml @@ -7,7 +7,7 @@ metadata: namespace: openshift-operators data: gitops.catalogSource: redhat-operators - gitops.channel: gitops-1.11 + gitops.channel: gitops-1.12 # gitops.sourceNamespace: GitOpsDefaultCatalogSourceNamespace # gitops.installApprovalPlan: GitOpsDefaultApprovalPlan @@ -26,7 +26,7 @@ spec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main gitOpsSpec: - operatorChannel: gitops-1.11 + operatorChannel: gitops-1.12 operatorSource: redhat-operators multiSourceConfig: enabled: false From 75c51cc6bc0cba6c9ae721b1aea5ff139d4e233a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 24 Apr 2024 15:57:09 +0200 Subject: [PATCH 055/222] Add overrides for MCE IIB We need to be able to explicitely override the Source and the Channel used to install the MCE multicluster-engine operator. The reason for this is that when we install ACM from an IIB, the default channel that will be used for MCE won't be present in the IIB, so we need to be able to be flexible in determining where the MCE gets installed from (sourcecatalog and channel) We default to redhat-operators because otherwise when installing gitops via IIB the ACM operator finds a channel for MCE that does not exist, so we force the source all the time. --- acm/templates/multiclusterhub.yaml | 8 +++++--- acm/values.yaml | 9 +++++++++ tests/acm-industrial-edge-factory.expected.yaml | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/acm/templates/multiclusterhub.yaml b/acm/templates/multiclusterhub.yaml index 79ef9339..a4e8b89b 100644 --- a/acm/templates/multiclusterhub.yaml +++ b/acm/templates/multiclusterhub.yaml @@ -1,3 +1,7 @@ +{{- $channel := "" }} +{{- if .Values.acm.mce_operator.channel }} +{{- $channel = printf ",\"channel\": \"%s\"" .Values.acm.mce_operator.channel }} +{{- end }} apiVersion: operator.open-cluster-management.io/v1 kind: MultiClusterHub metadata: @@ -5,7 +9,5 @@ metadata: namespace: open-cluster-management annotations: argocd.argoproj.io/sync-wave: "-1" - {{- if kindIs "map" .Values.clusterGroup.subscriptions }} - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "{{ default "redhat-operators" .Values.clusterGroup.subscriptions.acm.source }}" }' - {{- end }} + installer.open-cluster-management.io/mce-subscription-spec: '{"source": "{{ default "redhat-operators" .Values.acm.mce_operator.source }}" {{- $channel }} }' spec: {} diff --git a/acm/values.yaml b/acm/values.yaml index fb7cb03a..667bf89c 100644 --- a/acm/values.yaml +++ b/acm/values.yaml @@ -30,6 +30,15 @@ clusterGroup: # - name: clusterGroup # value: region-one +acm: + # Just used for IIB testing, drives the source and channel for the MCE + # subscription triggered by ACM + mce_operator: + source: redhat-operators + channel: null + + + secretStore: name: vault-backend kind: ClusterSecretStore diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index 0291231a..4f0ac751 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -22,6 +22,7 @@ metadata: namespace: open-cluster-management annotations: argocd.argoproj.io/sync-wave: "-1" + installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' spec: {} --- # Source: acm/templates/policies/ocp-gitops-policy.yaml From 8119368ab5387dc99c01021eea13138cb5f44294 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 30 Apr 2024 15:51:25 +0200 Subject: [PATCH 056/222] Update README for IIB changes --- ansible/roles/iib_ci/README.md | 38 +++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/ansible/roles/iib_ci/README.md b/ansible/roles/iib_ci/README.md index 6afccb1a..36784ed5 100644 --- a/ansible/roles/iib_ci/README.md +++ b/ansible/roles/iib_ci/README.md @@ -38,6 +38,8 @@ oc patch configs.imageregistry.operator.openshift.io cluster --type merge --patc oc patch configs.imageregistry.operator.openshift.io cluster --type merge --patch '{"spec":{"storage":{"emptyDir":{}}}}' ``` +### Gitops operator + Then in case of the `openshift-gitops-operator` we would install with: ```sh @@ -45,16 +47,42 @@ export CHANNEL=$(oc get -n openshift-marketplace packagemanifests -l "catalog=ii make EXTRA_HELM_OPTS="--set main.gitops.operatorSource=iib-${IIB} --set main.gitops.channel=${CHANNEL}" install ``` -To install ACM (`export OPERATOR=advanced-cluster-management`) or any other -operator (except the gitops one) from an IIB we would call the following as a -final step: +### ACM operator + +The advanced-cluster-management operator is a little bit more complex than the others because it +also installes another operator called MCE multicluster-engine. So to install ACM you typically +need two IIBs (one for acm and one for mce). With those two at hand, do the following (the ordering must be +consistent: the first IIB corresponds to the first OPERATOR, etc). + +```sh +export OPERATOR=advanced-cluster-management,multicluster-engine +export INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:713808,registry-proxy.engineering.redhat.com/rh-osbs/iib:718034 +make load-iib +``` + +Once the IIBs are loaded into the cluster we need to run the following steps: + +```sh +export ACM_CHANNEL=$(oc get -n openshift-marketplace packagemanifests -l "catalog=iib-713808" --field-selector "metadata.name=advanced-cluster-management" -o jsonpath='{.items[0].status.defaultChannel}') +export MCE_CHANNEL=$(oc get -n openshift-margetplace packagemanifests -l "catalog=iib-718034" --field-selector "metadata.name=multicluster-engine" -o jsonpath='{.items[0].status.defaultChannel}') +make EXTRA_HELM_OPTS="--set main.extraParameters[0].name=clusterGroup.subscriptions.acm.source --set main.extraParameters[0].value=iib-713808 \ + --set main.extraParameters[1].name=clusterGroup.subscriptions.acm.channel --set main.extraParameters[1].value=${ACM_CHANNEL} \ + --set main.extraParameters[2].name=acm.mce_operator.source --set main.extraParameters[2].value="iib-718034" \ + --set main.extraParameters[3].name=acm.mce_operator.channel --set main.extraParameters[3].value=${MCE_CHANNEL}" install +``` + +*Note*: In this case the `acm` in `clusterGroup.subscriptions.acm.*` is the name of the key in the subscriptions in `values-hub.yaml` + +### Other operators + +To install operators other than gitops and acm do the following: ```sh export CHANNEL=$(oc get -n openshift-marketplace packagemanifests -l "catalog=iib-${IIB}" --field-selector "metadata.name=${OPERATOR}" -o jsonpath='{.items[0].status.defaultChannel}') -make EXTRA_HELM_OPTS="--set main.extraParameters[0].name=clusterGroup.subscriptions.acm.source --set main.extraParameters[0].value=iib-${IIB} --set main.extraParameters[1].name=clusterGroup.subscriptions.acm.channel --set main.extraParameters[1].value=${CHANNEL}" install +make EXTRA_HELM_OPTS="--set main.extraParameters[0].name=clusterGroup.subscriptions..source --set main.extraParameters[0].value=iib-${IIB} --set main.extraParameters[1].name=clusterGroup.subscriptions..channel --set main.extraParameters[1].value=${CHANNEL}" install ``` -*Note*: In this case `acm` is the name of the subscription in `values-hub.yaml` +*Note*: Replace `` with the actual name of the subscription dictionary in `values-hub.yaml` ## Useful commands From 6a4e5c69f558d4cd689faabbfccb208142c739b2 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 2 May 2024 15:28:20 +0200 Subject: [PATCH 057/222] Release clustergroup v0.8.5 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index c8ba873f..e2d4f98b 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.4 +version: 0.8.5 From ff3147addcd49eaec6dee2de8bcc1ab4d676830b Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Thu, 2 May 2024 09:02:59 -0600 Subject: [PATCH 058/222] New global scope argocdServer section for values-global.yaml - Added new section for to configure the ArgoCD server to support tls argocdServer: route: tls: insecureEdgeTerminationPolicy: Redirect termination: reencrypt - Default for ArgoCD is to create route with the following: route: enabled tls: insecureEdgeTerminationPolicy: Redirect termination: passthrough For more information please refer to https://issues.redhat.com/browse/GITOPS-3918. - Changed default value for termination --- acm/templates/policies/ocp-gitops-policy.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index bec5b343..399f52a9 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -195,6 +195,11 @@ spec: memory: 128Mi route: enabled: true + {{- if and (.Values.global.argocdServer) (.Values.global.argocdServer.route) (.Values.global.argocdServer.route.tls) }} + tls: + insecureEdgeTerminationPolicy: {{ default "Redirect" .Values.global.argocdServer.route.tls.insecureEdgeTerminationPolicy }} + termination: {{ default "reencrypt" .Values.global.argocdServer.route.tls.termination }} + {{- end }} service: type: "" sso: From aa0b9699874de5fa5796c8957914525ea62fabf8 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 3 May 2024 13:49:49 +0200 Subject: [PATCH 059/222] Improve readme for ACM IIB --- ansible/roles/iib_ci/README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ansible/roles/iib_ci/README.md b/ansible/roles/iib_ci/README.md index 36784ed5..8c654dbb 100644 --- a/ansible/roles/iib_ci/README.md +++ b/ansible/roles/iib_ci/README.md @@ -52,12 +52,17 @@ make EXTRA_HELM_OPTS="--set main.gitops.operatorSource=iib-${IIB} --set main.git The advanced-cluster-management operator is a little bit more complex than the others because it also installes another operator called MCE multicluster-engine. So to install ACM you typically need two IIBs (one for acm and one for mce). With those two at hand, do the following (the ordering must be -consistent: the first IIB corresponds to the first OPERATOR, etc). +consistent: the first IIB corresponds to the first OPERATOR, etc). The following operation needs to be done +on both hub *and* spokes: ```sh -export OPERATOR=advanced-cluster-management,multicluster-engine -export INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:713808,registry-proxy.engineering.redhat.com/rh-osbs/iib:718034 -make load-iib +for i in hub-kubeconfig-file spoke-kubeconfig-file; do + export KUBECONFIG="${i}" + export KUBEADMINPASS="11111-22222-33333-44444" + export OPERATOR=advanced-cluster-management,multicluster-engine + export INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:713808,registry-proxy.engineering.redhat.com/rh-osbs/iib:718034 + make load-iib +done ``` Once the IIBs are loaded into the cluster we need to run the following steps: From 23614a40ae0fa1cbad3e6b69b1aae97da27279fe Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 3 May 2024 15:16:03 +0200 Subject: [PATCH 060/222] Drop gitopsspec from pattern's CR We drive this from the patterns-operator-config configmap these days, which makes more sense (it is a clusterwide setting and not really a per pattern one). --- operator-install/templates/pattern.yaml | 3 --- tests/operator-install-industrial-edge-factory.expected.yaml | 3 --- tests/operator-install-industrial-edge-hub.expected.yaml | 3 --- tests/operator-install-medical-diagnosis-hub.expected.yaml | 3 --- tests/operator-install-naked.expected.yaml | 3 --- tests/operator-install-normal.expected.yaml | 3 --- 6 files changed, 18 deletions(-) diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index ca3234f8..728726f0 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -12,9 +12,6 @@ spec: tokenSecret: {{ .Values.main.tokenSecret }} tokenSecretNamespace: {{ .Values.main.tokenSecretNamespace }} {{- end }} {{/* if and .Values.main.tokenSecret .Values.main.tokenSecretNamespace */}} - gitOpsSpec: - operatorChannel: {{ default "gitops-1.12" .Values.main.gitops.channel }} - operatorSource: {{ default "redhat-operators" .Values.main.gitops.operatorSource }} multiSourceConfig: enabled: {{ .Values.main.multiSourceConfig.enabled }} {{- if .Values.main.analyticsUUID }} diff --git a/tests/operator-install-industrial-edge-factory.expected.yaml b/tests/operator-install-industrial-edge-factory.expected.yaml index 018eb4c5..5e4aa02e 100644 --- a/tests/operator-install-industrial-edge-factory.expected.yaml +++ b/tests/operator-install-industrial-edge-factory.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/operator-install-industrial-edge-hub.expected.yaml b/tests/operator-install-industrial-edge-hub.expected.yaml index 018eb4c5..5e4aa02e 100644 --- a/tests/operator-install-industrial-edge-hub.expected.yaml +++ b/tests/operator-install-industrial-edge-hub.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/operator-install-medical-diagnosis-hub.expected.yaml b/tests/operator-install-medical-diagnosis-hub.expected.yaml index 018eb4c5..5e4aa02e 100644 --- a/tests/operator-install-medical-diagnosis-hub.expected.yaml +++ b/tests/operator-install-medical-diagnosis-hub.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/operator-install-naked.expected.yaml b/tests/operator-install-naked.expected.yaml index fc0d7699..3d58b474 100644 --- a/tests/operator-install-naked.expected.yaml +++ b/tests/operator-install-naked.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/operator-install-normal.expected.yaml b/tests/operator-install-normal.expected.yaml index 018eb4c5..5e4aa02e 100644 --- a/tests/operator-install-normal.expected.yaml +++ b/tests/operator-install-normal.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- From d9c7350f1bb700dbcf93d3421322da575f73ddf5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 3 May 2024 15:39:40 +0200 Subject: [PATCH 061/222] Allow customizing the VP operator subscription MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested with: ❯ helm template operator-install --show-only templates/subscription.yaml --set main.patternsOperator.installPlanApproval=Manual --- apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: patterns-operator namespace: openshift-operators labels: operators.coreos.com/patterns-operator.openshift-operators: "" spec: channel: fast installPlanApproval: Manual name: patterns-operator source: community-operators sourceNamespace: openshift-marketplace ❯ helm template operator-install --show-only templates/subscription.yaml --set main.patternsOperator.installPlanApproval=Manual --set main.patternsOperator.startingCSV=1.2.3 --- apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: patterns-operator namespace: openshift-operators labels: operators.coreos.com/patterns-operator.openshift-operators: "" spec: channel: fast installPlanApproval: Manual name: patterns-operator source: community-operators sourceNamespace: openshift-marketplace startingCSV: 1.2.3 --- operator-install/templates/subscription.yaml | 7 +++++-- operator-install/values.yaml | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/operator-install/templates/subscription.yaml b/operator-install/templates/subscription.yaml index 41d0d211..e8285cae 100644 --- a/operator-install/templates/subscription.yaml +++ b/operator-install/templates/subscription.yaml @@ -7,7 +7,10 @@ metadata: operators.coreos.com/patterns-operator.openshift-operators: "" spec: channel: {{ .Values.main.patternsOperator.channel }} - installPlanApproval: Automatic + installPlanApproval: {{ .Values.main.patternsOperator.installPlanApproval }} name: patterns-operator source: {{ .Values.main.patternsOperator.source }} - sourceNamespace: openshift-marketplace + sourceNamespace: {{ .Values.main.patternsOperator.sourceNamespace }} + {{- if .Values.main.patternsOperator.startingCSV }} + startingCSV: {{ .Values.main.patternsOperator.startingCSV }} + {{- end }} diff --git a/operator-install/values.yaml b/operator-install/values.yaml index 8ce7fe67..a46cca2e 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -20,6 +20,9 @@ main: patternsOperator: channel: fast source: community-operators + installPlanApproval: Automatic + sourceNamespace: openshift-marketplace + startingCSV: null clusterGroupName: default From 258af6b8a9d58a9cadeadf5fba2e91ff60eca629 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 6 May 2024 09:43:01 +0200 Subject: [PATCH 062/222] Add retries when checking oc version --- ansible/roles/iib_ci/tasks/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ansible/roles/iib_ci/tasks/main.yml b/ansible/roles/iib_ci/tasks/main.yml index fcaad76a..4e8df11f 100644 --- a/ansible/roles/iib_ci/tasks/main.yml +++ b/ansible/roles/iib_ci/tasks/main.yml @@ -17,6 +17,9 @@ ansible.builtin.shell: | oc get openshiftcontrollermanager/cluster -o yaml -o jsonpath='{.status.version}' register: oc_version_raw + retries: 10 + delay: 10 + until: oc_version_raw is not failed changed_when: false - name: Is OCP pre OCP 4.13? (aka registry supports v2 manifests) From 1cbcc9806685f3bc0ab5600659132022d8dfbc36 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 23 Apr 2024 11:35:18 +0200 Subject: [PATCH 063/222] Add an imperative-admin-sa service account --- .../templates/imperative/clusterrole.yaml | 16 ++++++++ clustergroup/templates/imperative/rbac.yaml | 21 +++++++++- .../templates/imperative/serviceaccount.yaml | 10 ++++- clustergroup/values.schema.json | 9 ++++ clustergroup/values.yaml | 4 ++ ...roup-industrial-edge-factory.expected.yaml | 41 ++++++++++++++++++- ...tergroup-industrial-edge-hub.expected.yaml | 41 ++++++++++++++++++- ...rgroup-medical-diagnosis-hub.expected.yaml | 41 ++++++++++++++++++- tests/clustergroup-naked.expected.yaml | 41 ++++++++++++++++++- tests/clustergroup-normal.expected.yaml | 41 ++++++++++++++++++- 10 files changed, 252 insertions(+), 13 deletions(-) diff --git a/clustergroup/templates/imperative/clusterrole.yaml b/clustergroup/templates/imperative/clusterrole.yaml index e3646917..0ad8ff64 100644 --- a/clustergroup/templates/imperative/clusterrole.yaml +++ b/clustergroup/templates/imperative/clusterrole.yaml @@ -1,5 +1,6 @@ {{- if not (eq .Values.enabled "plumbing") }} {{/* This is always defined as we always unseal the cluster with an imperative job */}} +{{- if $.Values.clusterGroup.imperative.serviceAccountCreate }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -18,4 +19,19 @@ rules: - list - watch {{- end }} +{{- end }} {{/* if $.Values.clusterGroup.imperative.serviceAccountCreate */}} +{{- if $.Values.clusterGroup.imperative.adminServiceAccountCreate }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ $.Values.clusterGroup.imperative.adminClusterRoleName }} +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +{{- end }} {{/* if $.Values.clusterGroup.imperative.adminServiceAccountCreate */}} {{- end }} diff --git a/clustergroup/templates/imperative/rbac.yaml b/clustergroup/templates/imperative/rbac.yaml index 1a4b3e2b..8bfad5b3 100644 --- a/clustergroup/templates/imperative/rbac.yaml +++ b/clustergroup/templates/imperative/rbac.yaml @@ -1,10 +1,11 @@ {{- if not (eq .Values.enabled "plumbing") }} {{/* This is always defined as we always unseal the cluster with an imperative job */}} +{{- if $.Values.clusterGroup.imperative.serviceAccountCreate -}} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: {{ $.Values.clusterGroup.imperative.namespace }}-cluster-admin-rolebinding + name: {{ $.Values.clusterGroup.imperative.namespace }}-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -17,7 +18,7 @@ subjects: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: {{ $.Values.clusterGroup.imperative.namespace }}-admin-rolebinding + name: {{ $.Values.clusterGroup.imperative.namespace }}-rolebinding namespace: {{ $.Values.clusterGroup.imperative.namespace }} roleRef: apiGroup: rbac.authorization.k8s.io @@ -28,3 +29,19 @@ subjects: name: {{ $.Values.clusterGroup.imperative.serviceAccountName }} namespace: {{ $.Values.clusterGroup.imperative.namespace }} {{- end }} +{{- if $.Values.clusterGroup.imperative.adminServiceAccountCreate }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ $.Values.clusterGroup.imperative.namespace }}-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ $.Values.clusterGroup.imperative.adminClusterRoleName }} +subjects: + - kind: ServiceAccount + name: {{ $.Values.clusterGroup.imperative.adminServiceAccountName }} + namespace: {{ $.Values.clusterGroup.imperative.namespace }} +{{- end }} +{{- end }} diff --git a/clustergroup/templates/imperative/serviceaccount.yaml b/clustergroup/templates/imperative/serviceaccount.yaml index ac051348..a171d300 100644 --- a/clustergroup/templates/imperative/serviceaccount.yaml +++ b/clustergroup/templates/imperative/serviceaccount.yaml @@ -1,10 +1,18 @@ {{- if not (eq .Values.enabled "plumbing") }} {{/* This is always defined as we always unseal the cluster with an imperative job */}} -{{- if $.Values.clusterGroup.imperative.serviceAccountCreate -}} +{{- if $.Values.clusterGroup.imperative.serviceAccountCreate }} apiVersion: v1 kind: ServiceAccount metadata: name: {{ $.Values.clusterGroup.imperative.serviceAccountName }} namespace: {{ $.Values.clusterGroup.imperative.namespace }} {{- end }} +{{- if $.Values.clusterGroup.imperative.adminServiceAccountCreate }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ $.Values.clusterGroup.imperative.adminServiceAccountName }} + namespace: {{ $.Values.clusterGroup.imperative.namespace }} +{{- end }} {{- end }} diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 071805fe..8d206957 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -677,6 +677,15 @@ }, "roleYaml": { "type": "string" + }, + "adminServiceAccountCreate": { + "type": "boolean" + }, + "adminServiceAccountName": { + "type": "string" + }, + "adminClusterRoleName": { + "type": "string" } }, "required": [ diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index c74db48c..c3611241 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -51,6 +51,10 @@ clusterGroup: clusterRoleYaml: "" roleName: imperative-role roleYaml: "" + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa + adminClusterRoleName: imperative-admin-cluster-role + managedClusterGroups: {} namespaces: [] # - name: factory diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index f34b5f18..c3eabd83 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -64,6 +64,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -116,6 +123,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -264,11 +274,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -278,6 +301,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -340,7 +377,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 6641ff73..393e530c 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -109,6 +109,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -237,6 +244,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -425,11 +435,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -439,6 +462,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -501,7 +538,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index a61ce547..f4933c53 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -109,6 +109,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -220,6 +227,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -352,11 +362,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -366,6 +389,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -428,7 +465,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index fdaf4293..6f1c6b2e 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -28,6 +28,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -43,6 +50,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -117,11 +127,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -131,6 +154,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -193,7 +230,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 93f6892a..baad3fd0 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -96,6 +96,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -128,6 +135,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -314,11 +324,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -328,6 +351,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -390,7 +427,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io From 3a4eaf900a3a2bae40730ab0a731972d590638fa Mon Sep 17 00:00:00 2001 From: "Sergio G." Date: Thu, 9 May 2024 22:12:08 +0200 Subject: [PATCH 064/222] Added support to label/annotate nodes --- clustergroup/templates/core/nodes.yaml | 25 ++++++ clustergroup/values.schema.json | 81 ++++++++++++++----- clustergroup/values.yaml | 7 +- examples/values-example.yaml | 11 +++ ...roup-industrial-edge-factory.expected.yaml | 1 + ...tergroup-industrial-edge-hub.expected.yaml | 1 + ...rgroup-medical-diagnosis-hub.expected.yaml | 1 + tests/clustergroup-naked.expected.yaml | 1 + tests/clustergroup-normal.expected.yaml | 37 +++++++++ 9 files changed, 142 insertions(+), 23 deletions(-) create mode 100644 clustergroup/templates/core/nodes.yaml diff --git a/clustergroup/templates/core/nodes.yaml b/clustergroup/templates/core/nodes.yaml new file mode 100644 index 00000000..5106447d --- /dev/null +++ b/clustergroup/templates/core/nodes.yaml @@ -0,0 +1,25 @@ +{{- if not (eq .Values.enabled "plumbing") }} +{{- range $node := .Values.clusterGroup.nodes }} +apiVersion: v1 +kind: Node +metadata: + {{- range $k, $v := $node }} + name: {{ $k }} + labels: + argocd.argoproj.io/managed-by: {{ $.Values.global.pattern }}-{{ $.Values.clusterGroup.name }} + {{- if $v.labels }} + {{- range $key, $value := $v.labels }} + {{ $key }}: {{ $value | default "" | quote }} + {{- end }} + {{- end }} + + {{- if $v.annotations }} + annotations: + {{- range $key, $value := $v.annotations }} + {{ $key }}: {{ $value | default "" | quote }} + {{- end }} + {{- end }}{{- /* if $v.annotations */}} + {{- end }}{{- /* range $k, $v := $node */}} +--- +{{- end -}} +{{- end -}} diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 8d206957..76c997b4 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -271,6 +271,20 @@ "$ref": "#/definitions/Namespaces" } }, + "nodes": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "object" + } + ], + "description": "Description of those nodes which ArgoCD will control the labels and/or annotations.", + "items": { + "$ref": "#/definitions/Nodes" + } + }, "indexImages": { "anyOf": [ { @@ -389,28 +403,51 @@ "type": "string" } ], - "description": "Description of the applications that will be created in the ArgoCD instances. The Application CRD is the Kubernetes resource object representing a deployed application instance in an environment. Two ways of defining applications: Using a list or using a dictionary.", - "additionalProperties": true, - "properties": { - "name": { - "type": "string", - "description": "Name of the namespace." - }, - "labels": { - "type": "array", - "items": { - "$ref": "#/definitions/NameValue" - } - }, - "annotations": { - "type": "array", - "items": { - "$ref": "#/definitions/NameValue" - } - } + "description": "Description of the applications that will be created in the ArgoCD instances. The Application CRD is the Kubernetes resource object representing a deployed application instance in an environment. Two ways of defining applications: Using a list or using a dictionary.", + "additionalProperties": true, + "properties": { + "name": { + "type": "string", + "description": "Name of the namespace." + }, + "labels": { + "type": "array", + "items": { + "$ref": "#/definitions/NameValue" + } + }, + "annotations": { + "type": "array", + "items": { + "$ref": "#/definitions/NameValue" } + } + } }, - "NameValue": { + "Nodes": { + "type": "object", + "description": "Description of those nodes which ArgoCD will control the labels and/or annotations.", + "additionalProperties": true, + "properties": { + "name": { + "type": "string", + "description": "Name of the node." + }, + "labels": { + "type": "array", + "items": { + "$ref": "#/definitions/NameValue" + } + }, + "annotations": { + "type": "array", + "items": { + "$ref": "#/definitions/NameValue" + } + } + } + }, + "NameValue": { "type": "object", "description": "Description of the applications that will be created in the ArgoCD instances. The Application CRD is the Kubernetes resource object representing a deployed application instance in an environment. Two ways of defining applications: Using a list or using a dictionary.", "additionalProperties": true, @@ -423,8 +460,8 @@ "type": "string", "description": "Name of the namespace." } - } - }, + } + }, "Applications": { "type": "object", "description": "Description of the applications that will be created in the ArgoCD instances. The Application CRD is the Kubernetes resource object representing a deployed application instance in an environment. Two ways of defining applications: Using a list or using a dictionary.", diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index c3611241..9b9f943e 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -10,7 +10,6 @@ global: installPlanApproval: Automatic applicationRetryLimit: 20 - enabled: "all" # Note that sometimes changing helm values might require a hard refresh (https://github.com/helm/helm/issues/3486) @@ -73,6 +72,12 @@ clusterGroup: # - OpenShift # # - open-cluster-management +# + nodes: [] +# nodes: +# - m-m00.mycluster.domain.tld: +# labels: +# cluster.ocs.openshift.io/openshift-storage: "" # subscriptions: {} # - name: advanced-cluster-management diff --git a/examples/values-example.yaml b/examples/values-example.yaml index 84682e20..542ec7c9 100644 --- a/examples/values-example.yaml +++ b/examples/values-example.yaml @@ -50,6 +50,17 @@ clusterGroup: - include-default-og: operatorGroup: true + nodes: + - m-m00.cluster.example.tld: + labels: + cluster.ocs.openshift.io/openshift-storage: "" + - m-m01.cluster.example.tld: + labels: + cluster.ocs.openshift.io/openshift-storage: "" + - m-m02.cluster.example.tld: + labels: + cluster.ocs.openshift.io/openshift-storage: "" + operatorgroupExcludes: - exclude-og diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index c3eabd83..c9911469 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -152,6 +152,7 @@ data: - manuela-stormshift-machine-sensor - manuela-stormshift-messaging - manuela-factory-ml-workspace + nodes: [] operatorgroupExcludes: - manuela-factory-ml-workspace projects: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 393e530c..7b2b387c 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -291,6 +291,7 @@ data: - manuela-data-lake - staging - vault + nodes: [] operatorgroupExcludes: - manuela-ml-workspace projects: diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index f4933c53..b20cde33 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -270,6 +270,7 @@ data: - staging - vault - golang-external-secrets + nodes: [] projects: - hub - medical-diagnosis diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 6f1c6b2e..d21a4f42 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -73,6 +73,7 @@ data: managedClusterGroups: {} name: example namespaces: [] + nodes: [] projects: [] sharedValueFiles: [] subscriptions: {} diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index baad3fd0..c7491805 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -234,6 +234,16 @@ data: operatorGroup: false - include-default-og: operatorGroup: true + nodes: + - m-m00.cluster.example.tld: + labels: + cluster.ocs.openshift.io/openshift-storage: "" + - m-m01.cluster.example.tld: + labels: + cluster.ocs.openshift.io/openshift-storage: "" + - m-m02.cluster.example.tld: + labels: + cluster.ocs.openshift.io/openshift-storage: "" operatorgroupExcludes: - exclude-og projects: @@ -1174,6 +1184,33 @@ spec: location: ApplicationMenu text: 'Example ArgoCD' --- +# Source: clustergroup/templates/core/nodes.yaml +apiVersion: v1 +kind: Node +metadata: + name: m-m00.cluster.example.tld + labels: + argocd.argoproj.io/managed-by: mypattern-example + cluster.ocs.openshift.io/openshift-storage: "" +--- +# Source: clustergroup/templates/core/nodes.yaml +apiVersion: v1 +kind: Node +metadata: + name: m-m01.cluster.example.tld + labels: + argocd.argoproj.io/managed-by: mypattern-example + cluster.ocs.openshift.io/openshift-storage: "" +--- +# Source: clustergroup/templates/core/nodes.yaml +apiVersion: v1 +kind: Node +metadata: + name: m-m02.cluster.example.tld + labels: + argocd.argoproj.io/managed-by: mypattern-example + cluster.ocs.openshift.io/openshift-storage: "" +--- # Source: clustergroup/templates/core/operatorgroup.yaml --- apiVersion: operators.coreos.com/v1 From 308d708f922e86383f8b4b8e1708a87d8625ff42 Mon Sep 17 00:00:00 2001 From: "Sergio G." Date: Thu, 9 May 2024 22:17:44 +0200 Subject: [PATCH 065/222] Added support to enable user workloads in control plane nodes --- clustergroup/templates/core/scheduler.yaml | 8 ++++++++ clustergroup/values.schema.json | 4 ++++ clustergroup/values.yaml | 2 ++ examples/values-example.yaml | 2 ++ tests/clustergroup-industrial-edge-factory.expected.yaml | 9 +++++++++ tests/clustergroup-industrial-edge-hub.expected.yaml | 9 +++++++++ tests/clustergroup-medical-diagnosis-hub.expected.yaml | 9 +++++++++ tests/clustergroup-naked.expected.yaml | 9 +++++++++ tests/clustergroup-normal.expected.yaml | 9 +++++++++ 9 files changed, 61 insertions(+) create mode 100644 clustergroup/templates/core/scheduler.yaml diff --git a/clustergroup/templates/core/scheduler.yaml b/clustergroup/templates/core/scheduler.yaml new file mode 100644 index 00000000..fd2cdb67 --- /dev/null +++ b/clustergroup/templates/core/scheduler.yaml @@ -0,0 +1,8 @@ +{{- if not (eq .Values.enabled "plumbing") }} +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: {{ $.Values.clusterGroup.mastersSchedulable }} +{{- end -}} diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 8d206957..8b6bfea6 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -257,6 +257,10 @@ "type": "array", "description": "Templated value file paths." }, + "mastersSchedulable": { + "type": "boolean", + "description": "if set to true, the control plane nodes will be marked as schedulable for user workloads also." + }, "namespaces": { "anyOf": [ { diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index c3611241..2b1018da 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -20,6 +20,8 @@ clusterGroup: targetCluster: in-cluster sharedValueFiles: [] + mastersSchedulable: false + argoCD: initContainers: [] configManagementPlugins: [] diff --git a/examples/values-example.yaml b/examples/values-example.yaml index 84682e20..d5b45f71 100644 --- a/examples/values-example.yaml +++ b/examples/values-example.yaml @@ -15,6 +15,8 @@ clusterGroup: - /values/{{ .Values.global.clusterPlatform }}.yaml - /values/{{ .Values.global.clusterVersion }}.yaml + mastersSchedulable: true + # # You can define namespaces using hashes and not as a list like so: # namespaces: diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index c3eabd83..727a2b4f 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -146,6 +146,7 @@ data: verbosity: "" isHubCluster: false managedClusterGroups: {} + mastersSchedulable: false name: factory namespaces: - manuela-stormshift-line-dashboard @@ -774,6 +775,14 @@ spec: targetNamespaces: - manuela-stormshift-messaging --- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: false +--- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 393e530c..cf2e69ea 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -280,6 +280,7 @@ data: - name: clusterGroup.isHubCluster value: "false" name: factory + mastersSchedulable: false name: datacenter namespaces: - golang-external-secrets @@ -1547,6 +1548,14 @@ spec: targetNamespaces: - vault --- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: false +--- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index f4933c53..3226ebd7 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -259,6 +259,7 @@ data: - name: clusterGroup.isHubCluster value: false name: region-one + mastersSchedulable: false name: hub namespaces: - open-cluster-management @@ -1705,6 +1706,14 @@ spec: targetNamespaces: - golang-external-secrets --- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: false +--- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 6f1c6b2e..5ab214b9 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -71,6 +71,7 @@ data: verbosity: "" isHubCluster: true managedClusterGroups: {} + mastersSchedulable: false name: example namespaces: [] projects: [] @@ -463,3 +464,11 @@ spec: href: 'https://example-gitops-server-common-example.' location: ApplicationMenu text: 'Example ArgoCD' +--- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: false diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index baad3fd0..18f43d52 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -211,6 +211,7 @@ data: - domain: syd.beekhof.net name: sydney name: argo-edge + mastersSchedulable: true name: example namespaces: - open-cluster-management: @@ -1217,6 +1218,14 @@ spec: targetNamespaces: - include-default-og --- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: true +--- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription From 0123fc78e1de0ba539ef968b71a58d696038f0a6 Mon Sep 17 00:00:00 2001 From: "Sergio G." Date: Fri, 10 May 2024 00:04:09 +0200 Subject: [PATCH 066/222] Added full support for the scheduler --- clustergroup/templates/core/scheduler.yaml | 5 ++++- clustergroup/values.schema.json | 6 +++--- clustergroup/values.yaml | 5 ++++- examples/values-example.yaml | 3 ++- tests/clustergroup-industrial-edge-factory.expected.yaml | 9 --------- tests/clustergroup-industrial-edge-hub.expected.yaml | 9 --------- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 9 --------- tests/clustergroup-naked.expected.yaml | 9 --------- tests/clustergroup-normal.expected.yaml | 3 ++- 9 files changed, 15 insertions(+), 43 deletions(-) diff --git a/clustergroup/templates/core/scheduler.yaml b/clustergroup/templates/core/scheduler.yaml index fd2cdb67..5061065e 100644 --- a/clustergroup/templates/core/scheduler.yaml +++ b/clustergroup/templates/core/scheduler.yaml @@ -1,8 +1,11 @@ {{- if not (eq .Values.enabled "plumbing") }} +{{- if hasKey .Values.clusterGroup "scheduler" }} apiVersion: config.openshift.io/v1 kind: Scheduler metadata: name: cluster spec: - mastersSchedulable: {{ $.Values.clusterGroup.mastersSchedulable }} +{{- toYaml .Values.clusterGroup.scheduler | nindent 2 }} {{- end -}} +{{- end -}} + diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 8b6bfea6..c4f97634 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -257,9 +257,9 @@ "type": "array", "description": "Templated value file paths." }, - "mastersSchedulable": { - "type": "boolean", - "description": "if set to true, the control plane nodes will be marked as schedulable for user workloads also." + "scheduler": { + "type": "object", + "description": "If set, it will become the spec of the scheduler/cluster in the managed cluster." }, "namespaces": { "anyOf": [ diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index 2b1018da..bb149567 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -20,7 +20,10 @@ clusterGroup: targetCluster: in-cluster sharedValueFiles: [] - mastersSchedulable: false +# scheduler: +# mastersSchedulable: true +# defaultNodeSelector: type=user-node,region=east +# profile: HighNodeUtilization argoCD: initContainers: [] diff --git a/examples/values-example.yaml b/examples/values-example.yaml index d5b45f71..0226efe7 100644 --- a/examples/values-example.yaml +++ b/examples/values-example.yaml @@ -15,7 +15,8 @@ clusterGroup: - /values/{{ .Values.global.clusterPlatform }}.yaml - /values/{{ .Values.global.clusterVersion }}.yaml - mastersSchedulable: true + scheduler: + mastersSchedulable: true # # You can define namespaces using hashes and not as a list like so: diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 727a2b4f..c3eabd83 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -146,7 +146,6 @@ data: verbosity: "" isHubCluster: false managedClusterGroups: {} - mastersSchedulable: false name: factory namespaces: - manuela-stormshift-line-dashboard @@ -775,14 +774,6 @@ spec: targetNamespaces: - manuela-stormshift-messaging --- -# Source: clustergroup/templates/core/scheduler.yaml -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: - mastersSchedulable: false ---- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index cf2e69ea..393e530c 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -280,7 +280,6 @@ data: - name: clusterGroup.isHubCluster value: "false" name: factory - mastersSchedulable: false name: datacenter namespaces: - golang-external-secrets @@ -1548,14 +1547,6 @@ spec: targetNamespaces: - vault --- -# Source: clustergroup/templates/core/scheduler.yaml -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: - mastersSchedulable: false ---- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 3226ebd7..f4933c53 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -259,7 +259,6 @@ data: - name: clusterGroup.isHubCluster value: false name: region-one - mastersSchedulable: false name: hub namespaces: - open-cluster-management @@ -1706,14 +1705,6 @@ spec: targetNamespaces: - golang-external-secrets --- -# Source: clustergroup/templates/core/scheduler.yaml -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: - mastersSchedulable: false ---- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 5ab214b9..6f1c6b2e 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -71,7 +71,6 @@ data: verbosity: "" isHubCluster: true managedClusterGroups: {} - mastersSchedulable: false name: example namespaces: [] projects: [] @@ -464,11 +463,3 @@ spec: href: 'https://example-gitops-server-common-example.' location: ApplicationMenu text: 'Example ArgoCD' ---- -# Source: clustergroup/templates/core/scheduler.yaml -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: - mastersSchedulable: false diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 18f43d52..3e2e2849 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -211,7 +211,6 @@ data: - domain: syd.beekhof.net name: sydney name: argo-edge - mastersSchedulable: true name: example namespaces: - open-cluster-management: @@ -239,6 +238,8 @@ data: - exclude-og projects: - datacenter + scheduler: + mastersSchedulable: true sharedValueFiles: - /values/aws.yaml - /values/4.12.yaml From 48b584e59c7129d104fa4b53b27cec11729cf09b Mon Sep 17 00:00:00 2001 From: "Sergio G." Date: Fri, 10 May 2024 00:21:37 +0200 Subject: [PATCH 067/222] Simplified PR for auto approve install plans --- .../auto-approve-installplans.yaml | 40 ++++++++++++++ .../imperative/auto-approve-installplans.yaml | 52 +++++++++++++++++++ clustergroup/values.schema.json | 4 ++ 3 files changed, 96 insertions(+) create mode 100644 ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml create mode 100644 clustergroup/templates/imperative/auto-approve-installplans.yaml diff --git a/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml b/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml new file mode 100644 index 00000000..6b6802d4 --- /dev/null +++ b/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml @@ -0,0 +1,40 @@ +# This playbook will watch for pending install plans of managed operators +# if they are in Manual and there's a startingCSV that must be installed +--- +- name: InstallPlan Auto-Approver + hosts: localhost + connection: local + gather_facts: false + become: false + + tasks: + - name: Get all installPlans from OpenShift + kubernetes.core.k8s_info: + api_version: operators.coreos.com/v1alpha1 + kind: InstallPlan + register: installplans + + - name: Get required CSVs from clusterGroup data + ansible.builtin.set_fact: + expected_csv: "{{ expected_csv | default([]) + [item.csv] }}" + when: item.csv | default(false) and + ((item.installPlanApproval | default("") == "Manual") or + (item.installPlanApproval | default("") == "" and global.options.installPlanApproval | default("") == "Manual")) + with_items: "{{ clusterGroup.subscriptions.values() }}" + + # TODO: loop over clusterGroup.subscriptions instead of installplans + # to allow certain control on the order of approvals + # IDEA: allow adding a per-installplan delay after the approval before + # moving forward to the next one + - name: Approve the missing installPlans + kubernetes.core.k8s_json_patch: + api_version: operators.coreos.com/v1alpha1 + kind: InstallPlan + name: "{{ item.metadata.name }}" + namespace: "{{ item.metadata.namespace }}" + patch: + - op: replace + path: /spec/approved + value: true + when: (item.spec.clusterServiceVersionNames | intersect(expected_csv | default([]))) | length > 0 + loop: "{{ installplans.resources }}" diff --git a/clustergroup/templates/imperative/auto-approve-installplans.yaml b/clustergroup/templates/imperative/auto-approve-installplans.yaml new file mode 100644 index 00000000..e6ebf26c --- /dev/null +++ b/clustergroup/templates/imperative/auto-approve-installplans.yaml @@ -0,0 +1,52 @@ +{{- if $.Values.global.options.autoApproveManualInstallPlans }} +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: auto-approve-installplans-cronjob + namespace: {{ $.Values.clusterGroup.imperative.namespace}} +spec: + schedule: "*/5 * * * *" + # if previous Job is still running, skip execution of a new Job + concurrencyPolicy: Forbid + jobTemplate: + spec: + activeDeadlineSeconds: {{ $.Values.clusterGroup.imperative.activeDeadlineSeconds }} + template: + metadata: + name: auto-approve-installplans-job + spec: + serviceAccountName: {{ $.Values.clusterGroup.imperative.serviceAccountName }} + initContainers: + # git init happens in /git/repo so that we can set the folder to 0770 permissions + # reason for that is ansible refuses to create temporary folders in there + {{- include "imperative.initcontainers.gitinit" . | indent 12 }} + - name: auto-approve-installplans + image: {{ $.Values.clusterGroup.imperative.image }} + imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} + env: + - name: HOME + value: /git/home + workingDir: /git/repo + command: + - timeout + - {{ .timeout | default "600" | quote }} + - ansible-playbook + {{- if $.Values.clusterGroup.imperative.verbosity }} + - {{ $.Values.clusterGroup.imperative.verbosity }} + {{- end }} + - -e + - "@/values/values.yaml" + - common/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml + volumeMounts: + {{- include "imperative.volumemounts" . | indent 16 }} + containers: + {{- include "imperative.containers.done" . | indent 12 }} + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} + restartPolicy: Never +{{- end }} diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 8d206957..9c3a3651 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -226,6 +226,10 @@ "deprecated": true, "description": "This is used to approval strategy for the subscriptions of OpenShift Operators being installed. You can choose Automatic or Manual updates. NOTE: This setting is now available in the subcriptions description in the values file." }, + "autoApproveManualInstallPlans": { + "type": "boolean", + "description": "This is used to approve automatically those subscriptions of OpenShift Operators that are in Manual with a startingCSV version. You can choose True or False. Defaults: False." + }, "applicationRetryLimit": { "type": "integer", "description": "Number of failed sync attempt retries; unlimited number of attempts if less than 0" From 04a6d6dbb3a04f40d879bdbfed8c2a9e47a15e32 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 13 May 2024 23:09:15 +0200 Subject: [PATCH 068/222] Switch to registry.redhat.io for the initContainer image This makes the registry url more consistent with what we already use (e.g. in the imperative templates) --- acm/templates/policies/ocp-gitops-policy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index 399f52a9..e72434ae 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -140,7 +140,7 @@ spec: - -c - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true - image: registry.access.redhat.com/ubi9/ubi-minimal:latest + image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca resources: {} volumeMounts: From f6c7a47c1b6e8637339bb5678bd785648a8ad3c1 Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Tue, 14 May 2024 14:42:27 -0600 Subject: [PATCH 069/222] Update for ACM chart to application-policies.yaml - If statement was checking for .Values.global.extraValueFiles. - We now checking at the .extraValueFiles in the managedClusterGroups section. managedClusterGroups: aro-prod: name: innovation acmlabels: - name: clusterGroup value: innovation extraValueFiles: - '/overrides/values-common-capabilities.yaml' helmOverrides: - name: clusterGroup.isHubCluster value: "false" --- acm/templates/policies/application-policies.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 131f4f3e..0194d6bb 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -45,7 +45,7 @@ spec: ignoreMissingValueFiles: true valueFiles: {{- include "acm.app.policies.valuefiles" . | nindent 22 }} - {{- range $valueFile := $.Values.global.extraValueFiles }} + {{- range $valueFile := .extraValueFiles }} - {{ $valueFile | quote }} {{- end }} parameters: From 4d422a4e7e3d78fba1f0420790e586f01461ad03 Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Wed, 15 May 2024 17:12:30 -0600 Subject: [PATCH 070/222] Add extraParameters to values.schema.json - Problem Statement The current **clustergroup** schema does not allow the definition of **extraParameters** under the **main** section of a values file. - Caveat The user defined variables in the **extraParameters** section would only be applied if the user deploys the pattern via the command, using `./pattern.sh make install` or `./pattern.sh make operator-deploy` and not via the OpenShift Validated Patterns Operator UI. - Fix Description Add the **extraParameters** to the definition of **Main.properties** in the values.schema.json: "extraParameters": { "type": "array", "description": "Pass in extra Helm parameters to all ArgoCD Applications and the framework." }, - This will allow users to define extra parameters that will be added by the framework to the ArgoCD applications it creates. - For more information see https://github.com/validatedpatterns/common/issues/510 --- clustergroup/values.schema.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 8d206957..ea115f2a 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -65,6 +65,10 @@ "clusterGroupName": { "type": "string" }, + "extraParameters": { + "type": "array", + "description": "Pass in extra Helm parameters to all ArgoCD Applications and the framework." + }, "experimentalCapabilities": { "type": "string", "description": "String to enable certain experimental capabilities in the operator and the framework." From ab630bb7953a1fcf84945e923a21e537e899a3ee Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 17 May 2024 10:28:49 +0200 Subject: [PATCH 071/222] Update ESO to 0.9.18 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.9.16.tgz | Bin 102068 -> 0 bytes .../charts/external-secrets-0.9.18.tgz | Bin 0 -> 76336 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 159 +++++++++++------- ...-secrets-industrial-edge-hub.expected.yaml | 159 +++++++++++------- ...ecrets-medical-diagnosis-hub.expected.yaml | 159 +++++++++++------- ...olang-external-secrets-naked.expected.yaml | 159 +++++++++++------- ...lang-external-secrets-normal.expected.yaml | 159 +++++++++++------- 9 files changed, 514 insertions(+), 289 deletions(-) delete mode 100644 golang-external-secrets/charts/external-secrets-0.9.16.tgz create mode 100644 golang-external-secrets/charts/external-secrets-0.9.18.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 961f3b29..4aef19aa 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.0.3 dependencies: - name: external-secrets - version: "0.9.16" + version: "0.9.18" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.9.16.tgz b/golang-external-secrets/charts/external-secrets-0.9.16.tgz deleted file mode 100644 index ca268d8459d75ca2b82392618d1bda98327bb264..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102068 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