From e41999366e233e57b08a4084266cecc3f76d3f1f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Sep 2024 00:54:14 +0000 Subject: [PATCH] Added chart versions: cockroach-labs/cockroachdb: - 14.0.1 codefresh/cf-runtime: - 6.3.58 external-secrets/external-secrets: - 0.10.3 --- assets/cockroach-labs/cockroachdb-14.0.1.tgz | Bin 0 -> 31735 bytes assets/codefresh/cf-runtime-6.3.58.tgz | Bin 0 -> 43669 bytes .../external-secrets-0.10.3.tgz | Bin 0 -> 87030 bytes .../cockroachdb/14.0.1/CONTRIBUTING.md | 14 + .../cockroachdb/14.0.1/Chart.yaml | 18 + .../cockroachdb/14.0.1/README.md | 586 +++ .../cockroachdb/14.0.1/app-readme.md | 9 + .../cockroachdb/14.0.1/templates/NOTES.txt | 50 + .../cockroachdb/14.0.1/templates/_helpers.tpl | 291 ++ .../14.0.1/templates/backendconfig.yaml | 21 + .../14.0.1/templates/certificate.ca.yaml | 33 + .../14.0.1/templates/certificate.client.yaml | 40 + .../14.0.1/templates/certificate.issuer.yaml | 20 + .../14.0.1/templates/certificate.node.yaml | 50 + .../14.0.1/templates/clusterrole.yaml | 19 + .../14.0.1/templates/clusterrolebinding.yaml | 23 + .../templates/cronjob-ca-certSelfSigner.yaml | 46 + .../cronjob-client-node-certSelfSigner.yaml | 53 + .../cockroachdb/14.0.1/templates/ingress.yaml | 90 + .../14.0.1/templates/job-certSelfSigner.yaml | 83 + .../14.0.1/templates/job-cleaner.yaml | 55 + .../14.0.1/templates/job.init.yaml | 296 ++ .../14.0.1/templates/networkpolicy.yaml | 59 + .../14.0.1/templates/poddisruptionbudget.yaml | 26 + .../templates/role-certRotateSelfSigner.yaml | 27 + .../14.0.1/templates/role-certSelfSigner.yaml | 33 + .../cockroachdb/14.0.1/templates/role.yaml | 23 + .../rolebinding-certRotateSelfSigner.yaml | 23 + .../templates/rolebinding-certSelfSigner.yaml | 29 + .../14.0.1/templates/rolebinding.yaml | 23 + .../templates/secret.backendconfig.yaml | 25 + .../14.0.1/templates/secret.logconfig.yaml | 19 + .../14.0.1/templates/secret.registry.yaml | 23 + .../14.0.1/templates/secrets.init.yaml | 20 + .../14.0.1/templates/service.discovery.yaml | 64 + .../14.0.1/templates/service.public.yaml | 55 + .../14.0.1/templates/serviceMonitor.yaml | 54 + .../serviceaccount-certRotateSelfSigner.yaml | 22 + .../serviceaccount-certSelfSigner.yaml | 25 + .../14.0.1/templates/serviceaccount.yaml | 21 + .../14.0.1/templates/statefulset.yaml | 402 ++ .../14.0.1/templates/tests/client.yaml | 65 + .../cockroachdb/14.0.1/values.schema.json | 97 + .../cockroachdb/14.0.1/values.yaml | 590 +++ .../codefresh/cf-runtime/6.3.58/.helmignore | 3 + charts/codefresh/cf-runtime/6.3.58/Chart.yaml | 28 + charts/codefresh/cf-runtime/6.3.58/README.md | 1228 +++++ .../cf-runtime/6.3.58/README.md.gotmpl | 1007 ++++ .../6.3.58/files/cleanup-runtime.sh | 37 + .../6.3.58/files/configure-dind-certs.sh | 132 + .../cf-runtime/6.3.58/files/init-runtime.sh | 80 + .../6.3.58/files/reconcile-runtime.sh | 38 + .../_components/app-proxy/_deployment.yaml | 70 + .../_components/app-proxy/_env-vars.yaml | 19 + .../_components/app-proxy/_helpers.tpl | 43 + .../_components/app-proxy/_ingress.yaml | 32 + .../_components/app-proxy/_rbac.yaml | 47 + .../_components/app-proxy/_service.yaml | 17 + .../event-exporter/_deployment.yaml | 62 + .../_components/event-exporter/_env-vars.yaml | 14 + .../_components/event-exporter/_helpers.tpl | 43 + .../_components/event-exporter/_rbac.yaml | 47 + .../_components/event-exporter/_service.yaml | 17 + .../event-exporter/_serviceMontor.yaml | 14 + .../_components/monitor/_deployment.yaml | 70 + .../_components/monitor/_env-vars.yaml | 26 + .../_components/monitor/_helpers.tpl | 42 + .../templates/_components/monitor/_rbac.yaml | 56 + .../_components/monitor/_service.yaml | 17 + .../_components/runner/_deployment.yaml | 103 + .../templates/_components/runner/_helpers.tpl | 42 + .../templates/_components/runner/_rbac.yaml | 53 + .../_init-container.yaml | 30 + .../_main-container.yaml | 28 + .../_sidecar-container.yaml | 22 + .../volume-provisioner/_cronjob.yaml | 58 + .../volume-provisioner/_daemonset.yaml | 98 + .../volume-provisioner/_deployment.yaml | 67 + .../volume-provisioner/_env-vars.yaml | 88 + .../volume-provisioner/_helpers.tpl | 93 + .../_components/volume-provisioner/_rbac.yaml | 71 + .../volume-provisioner/_secret.yaml | 22 + .../volume-provisioner/_storageclass.yaml | 47 + .../cf-runtime/6.3.58/templates/_helpers.tpl | 51 + .../templates/app-proxy/deployment.yaml | 9 + .../6.3.58/templates/app-proxy/ingress.yaml | 9 + .../6.3.58/templates/app-proxy/rbac.yaml | 9 + .../6.3.58/templates/app-proxy/service.yaml | 9 + .../templates/event-exporter/deployment.yaml | 9 + .../6.3.58/templates/event-exporter/rbac.yaml | 9 + .../templates/event-exporter/service.yaml | 11 + .../templates/extra/extra-resources.yaml | 6 + .../templates/extra/runtime-images-cm.yaml | 19 + .../hooks/post-install/cm-update-runtime.yaml | 18 + .../hooks/post-install/job-gencerts-dind.yaml | 68 + .../post-install/job-update-runtime.yaml | 77 + .../post-install/rbac-gencerts-dind.yaml | 37 + .../pre-delete/job-cleanup-resources.yaml | 73 + .../pre-delete/rbac-cleanup-resources.yaml | 46 + .../6.3.58/templates/monitor/deployment.yaml | 9 + .../6.3.58/templates/monitor/rbac.yaml | 9 + .../6.3.58/templates/monitor/service.yaml | 9 + .../templates/other/external-secrets.yaml | 2 + .../6.3.58/templates/other/podMonitor.yaml | 2 + .../templates/other/serviceMonitor.yaml | 2 + .../6.3.58/templates/runner/deployment.yaml | 9 + .../6.3.58/templates/runner/rbac.yaml | 9 + .../6.3.58/templates/runtime/_helpers.tpl | 123 + .../templates/runtime/cm-dind-daemon.yaml | 10 + .../6.3.58/templates/runtime/rbac.yaml | 48 + .../runtime/runtime-env-spec-tmpl.yaml | 211 + .../6.3.58/templates/runtime/secret.yaml | 11 + .../6.3.58/templates/runtime/svc-dind.yaml | 16 + .../templates/volume-provisioner/cronjob.yaml | 11 + .../volume-provisioner/daemonset.yaml | 11 + .../volume-provisioner/deployment.yaml | 10 + .../templates/volume-provisioner/rbac.yaml | 9 + .../templates/volume-provisioner/secret.yaml | 10 + .../volume-provisioner/storageclass.yaml | 10 + .../codefresh/cf-runtime/6.3.58/values.yaml | 947 ++++ .../external-secrets/0.10.3/Chart.lock | 6 + .../external-secrets/0.10.3/Chart.yaml | 25 + .../external-secrets/0.10.3/README.md | 225 + .../external-secrets/0.10.3/app-readme.md | 7 + .../charts/bitwarden-sdk-server/.helmignore | 23 + .../charts/bitwarden-sdk-server/Chart.yaml | 6 + .../bitwarden-sdk-server/templates/NOTES.txt | 22 + .../templates/_helpers.tpl | 62 + .../templates/deployment.yaml | 77 + .../templates/service.yaml | 14 + .../templates/serviceaccount.yaml | 12 + .../__snapshot__/deployment_test.yaml.snap | 60 + .../tests/deployment_test.yaml | 9 + .../charts/bitwarden-sdk-server/values.yaml | 98 + .../external-secrets/0.10.3/questions.yaml | 8 + .../0.10.3/templates/NOTES.txt | 7 + .../0.10.3/templates/_helpers.tpl | 198 + .../templates/cert-controller-deployment.yaml | 124 + .../cert-controller-poddisruptionbudget.yaml | 19 + .../templates/cert-controller-rbac.yaml | 86 + .../templates/cert-controller-service.yaml | 28 + .../cert-controller-serviceaccount.yaml | 16 + .../0.10.3/templates/crds/acraccesstoken.yaml | 203 + .../templates/crds/clusterexternalsecret.yaml | 666 +++ .../templates/crds/clustersecretstore.yaml | 4601 +++++++++++++++++ .../templates/crds/ecrauthorizationtoken.yaml | 177 + .../0.10.3/templates/crds/externalsecret.yaml | 820 +++ .../0.10.3/templates/crds/fake.yaml | 86 + .../0.10.3/templates/crds/gcraccesstoken.yaml | 138 + .../templates/crds/githubaccesstoken.yaml | 112 + .../0.10.3/templates/crds/password.yaml | 108 + .../0.10.3/templates/crds/pushsecret.yaml | 386 ++ .../0.10.3/templates/crds/secretstore.yaml | 4601 +++++++++++++++++ .../0.10.3/templates/crds/uuid.yaml | 72 + .../templates/crds/vaultdynamicsecret.yaml | 707 +++ .../0.10.3/templates/crds/webhook.yaml | 157 + .../0.10.3/templates/deployment.yaml | 146 + .../0.10.3/templates/extra-manifests.yaml | 4 + .../0.10.3/templates/poddisruptionbudget.yaml | 19 + .../0.10.3/templates/rbac.yaml | 301 ++ .../0.10.3/templates/service.yaml | 28 + .../0.10.3/templates/serviceaccount.yaml | 16 + .../0.10.3/templates/servicemonitor.yaml | 164 + .../0.10.3/templates/validatingwebhook.yaml | 78 + .../0.10.3/templates/webhook-certificate.yaml | 30 + .../0.10.3/templates/webhook-deployment.yaml | 128 + .../webhook-poddisruptionbudget.yaml | 20 + .../0.10.3/templates/webhook-secret.yaml | 14 + .../0.10.3/templates/webhook-service.yaml | 37 + .../templates/webhook-serviceaccount.yaml | 16 + .../0.10.3/values.schema.json | 905 ++++ .../external-secrets/0.10.3/values.yaml | 532 ++ index.yaml | 85 +- 173 files changed, 25959 insertions(+), 1 deletion(-) create mode 100644 assets/cockroach-labs/cockroachdb-14.0.1.tgz create mode 100644 assets/codefresh/cf-runtime-6.3.58.tgz create mode 100644 assets/external-secrets/external-secrets-0.10.3.tgz create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/CONTRIBUTING.md create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/Chart.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/README.md create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/app-readme.md create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/NOTES.txt create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/_helpers.tpl create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/backendconfig.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.ca.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.client.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.issuer.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.node.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/clusterrole.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/clusterrolebinding.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/cronjob-ca-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/cronjob-client-node-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/ingress.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/job-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/job-cleaner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/job.init.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/networkpolicy.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/poddisruptionbudget.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/role-certRotateSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/role-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/role.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding-certRotateSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.backendconfig.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.logconfig.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.registry.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/secrets.init.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/service.discovery.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/service.public.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceMonitor.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount-certRotateSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/statefulset.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/templates/tests/client.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/values.schema.json create mode 100644 charts/cockroach-labs/cockroachdb/14.0.1/values.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/.helmignore create mode 100644 charts/codefresh/cf-runtime/6.3.58/Chart.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/README.md create mode 100644 charts/codefresh/cf-runtime/6.3.58/README.md.gotmpl create mode 100644 charts/codefresh/cf-runtime/6.3.58/files/cleanup-runtime.sh create mode 100644 charts/codefresh/cf-runtime/6.3.58/files/configure-dind-certs.sh create mode 100644 charts/codefresh/cf-runtime/6.3.58/files/init-runtime.sh create mode 100644 charts/codefresh/cf-runtime/6.3.58/files/reconcile-runtime.sh create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_env-vars.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_helpers.tpl create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_ingress.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_service.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_env-vars.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_helpers.tpl create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_service.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_serviceMontor.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_env-vars.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_helpers.tpl create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_service.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_helpers.tpl create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_init-container.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_main-container.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_sidecar-container.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_cronjob.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_daemonset.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_env-vars.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_helpers.tpl create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_secret.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_storageclass.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/_helpers.tpl create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/ingress.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/service.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/service.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/extra/extra-resources.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/extra/runtime-images-cm.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/cm-update-runtime.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/job-gencerts-dind.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/job-update-runtime.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/rbac-gencerts-dind.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/hooks/pre-delete/job-cleanup-resources.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/hooks/pre-delete/rbac-cleanup-resources.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/monitor/deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/monitor/rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/monitor/service.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/other/external-secrets.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/other/podMonitor.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/other/serviceMonitor.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/runner/deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/runner/rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/runtime/_helpers.tpl create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/runtime/cm-dind-daemon.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/runtime/rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/runtime/runtime-env-spec-tmpl.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/runtime/secret.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/runtime/svc-dind.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/cronjob.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/daemonset.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/deployment.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/rbac.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/secret.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/storageclass.yaml create mode 100644 charts/codefresh/cf-runtime/6.3.58/values.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/Chart.lock create mode 100644 charts/external-secrets/external-secrets/0.10.3/Chart.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/README.md create mode 100644 charts/external-secrets/external-secrets/0.10.3/app-readme.md create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/.helmignore create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/Chart.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/NOTES.txt create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/_helpers.tpl create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/deployment.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/service.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/serviceaccount.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/tests/__snapshot__/deployment_test.yaml.snap create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/tests/deployment_test.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/values.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/questions.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/NOTES.txt create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/_helpers.tpl create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-deployment.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-poddisruptionbudget.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-rbac.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-service.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-serviceaccount.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/acraccesstoken.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/clusterexternalsecret.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/clustersecretstore.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/ecrauthorizationtoken.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/externalsecret.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/fake.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/gcraccesstoken.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/githubaccesstoken.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/password.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/pushsecret.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/secretstore.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/uuid.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/vaultdynamicsecret.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/crds/webhook.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/deployment.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/extra-manifests.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/poddisruptionbudget.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/rbac.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/service.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/serviceaccount.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/servicemonitor.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/validatingwebhook.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/webhook-certificate.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/webhook-deployment.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/webhook-poddisruptionbudget.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/webhook-secret.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/webhook-service.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/templates/webhook-serviceaccount.yaml create mode 100644 charts/external-secrets/external-secrets/0.10.3/values.schema.json create mode 100644 charts/external-secrets/external-secrets/0.10.3/values.yaml diff --git a/assets/cockroach-labs/cockroachdb-14.0.1.tgz b/assets/cockroach-labs/cockroachdb-14.0.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..5de092b93fdff5cb52b4786053289329de4c71f1 GIT binary patch literal 31735 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 ei~RZd^YiED&(FW==l=%)0RR8}K#N=eDc zVQyr3R8em|NM&qo0POwiavL|(Fp9pvc@+qquOjL73=cZk;eL|+(iAN-)`1^MIgj6z ziyF;q*#CE}Rkbc-UC(y|>lRkwG=n*jLrS7#n|SJRL=4bqG=N5< z(df2E2AO#Qn!-wJVv)d{TT}Nx?l)Dd)#}l~0sn8cT2219c5qPrkJ`b}(Tf+ggX+=Y ze^hJx^`qK*fEppj(f#zz!P zfDIXZWLp6QmgfMUpj-C$4V(ktqVyvsPB{Y&>;)F`Xdl`$f`a*_?^pptt30w?3Rw-? z3M?0oP1_0r7xGG?E$B3WZ;`-*B(s=} ze*L9p)?OObpE3&*=t7G^2{>A3CCf+e6pY(?$$>uf9O&5y(niSuVR;)*r`Rh2K%kE) z3NV>7(z~!xshDhNNI)xkxe&9eSvxYTrP$Ck!5ipK0j~x|m_%I#y_v_TGr_FkNf7w7 zQK{JKGwVwU*$jqk+@cf)w8HW@0SG5`^6FbclQAmG$Oe25{@ zX`l_pjJO%N83>zWq^3zJMQVy?#1>>#b!BlIPh(&zx6s3$RSIc%WbT`XFH4WTJ|8-1 z{QuT+XOKR?2C$g_AML+*QA_gw!~LTz|KCJ<1`GrA1HxEzfH|i`mg~*|zJ-J!2Wrd7 z9L-#ptuYY5sqZqzz4H;dE>No%1QQ4(-{Wg|moLc+3913g-37p*uH^8ZdnA55e>+^1Vlzp z{^spv)>AbAg*Jf!?>hw+1r{Mz2&X%9-99fs8{m%*B?arUcgpt5h#_}fD;Qxi1v>=( zHA4hCKkTwSMiqF2Y0v=WkfoVAvkpz9B-#`x_5BM%0AowYWpaL`kSArlBhykl1 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 J1`q%`1OR2d*8uDc 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
    =1YQK6f2vYk+a6?4ZR; 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 `4.1.4`. For changes which +affect the backwards compatibility of the chart, the major version must be +incremented, e.g. `4.1.3` -> `5.0.0`. Examples of changes which affect backwards +compatibility include any major version releases of CockroachDB, as well as any +breaking changes to the CockroachDB chart templates. + diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/Chart.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/Chart.yaml new file mode 100644 index 000000000..62d908721 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/Chart.yaml @@ -0,0 +1,18 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: CockroachDB + catalog.cattle.io/kube-version: '>=1.8-0' + catalog.cattle.io/release-name: cockroachdb +apiVersion: v1 +appVersion: 24.2.1 +description: CockroachDB is a scalable, survivable, strongly-consistent SQL database. +home: https://www.cockroachlabs.com +icon: file://assets/icons/cockroachdb.png +kubeVersion: '>=1.8-0' +maintainers: +- email: helm-charts@cockroachlabs.com + name: cockroachlabs +name: cockroachdb +sources: +- https://github.com/cockroachdb/cockroach +version: 14.0.1 diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/README.md b/charts/cockroach-labs/cockroachdb/14.0.1/README.md new file mode 100644 index 000000000..4c9f5425f --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/README.md @@ -0,0 +1,586 @@ + +# CockroachDB Helm Chart + +[CockroachDB](https://github.com/cockroachdb/cockroach) - the open source, cloud-native distributed SQL database. + +## Documentation + +Below is a brief overview of operating the CockroachDB Helm Chart and some specific implementation details. For additional information on deploying CockroachDB, please see: +> + +Note that the documentation requires Helm 3.0 or higher. + +## Prerequisites Details + +* Kubernetes 1.8 +* PV support on the underlying infrastructure (only if using `storage.persistentVolume`). [Docker for windows hostpath provisioner is not supported](https://github.com/cockroachdb/docs/issues/3184). +* If you want to secure your cluster to use TLS certificates for all network communication, [Helm must be installed with RBAC privileges](https://helm.sh/docs/topics/rbac/) or else you will get an "attempt to grant extra privileges" error. + +## StatefulSet Details + +* + +## StatefulSet Caveats + +* + +## Chart Details + +This chart will do the following: + +* Set up a dynamically scalable CockroachDB cluster using a Kubernetes StatefulSet. + +## Add the CockroachDB Repository + +```shell +helm repo add cockroachdb https://charts.cockroachdb.com/ +``` + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```shell +helm install my-release cockroachdb/cockroachdb +``` + +Note that for a production cluster, you will likely want to override the following parameters in [`values.yaml`](values.yaml) with your own values. + +- `statefulset.resources.requests.memory` and `statefulset.resources.limits.memory` allocate memory resources to CockroachDB pods in your cluster. +- `conf.cache` and `conf.max-sql-memory` are memory limits that we recommend setting to 1/4 of the above resource allocation. When running CockroachDB, you must set these limits explicitly to avoid running out of memory. +- `storage.persistentVolume.size` defaults to `100Gi` of disk space per pod, which you may increase or decrease for your use case. +- `storage.persistentVolume.storageClass` uses the default storage class for your environment. We strongly recommend that you specify a storage class which uses an SSD. +- `tls.enabled` must be set to `yes`/`true` to deploy in secure mode. + +For more information on overriding the `values.yaml` parameters, please see: +> + +Confirm that all pods are `Running` successfully and init has been completed: + +```shell +kubectl get pods +``` + +``` +NAME READY STATUS RESTARTS AGE +my-release-cockroachdb-0 1/1 Running 0 1m +my-release-cockroachdb-1 1/1 Running 0 1m +my-release-cockroachdb-2 1/1 Running 0 1m +my-release-cockroachdb-init-k6jcr 0/1 Completed 0 1m +``` + +Confirm that persistent volumes are created and claimed for each pod: + +```shell +kubectl get pv +``` + +``` +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE +pvc-64878ebf-f3f0-11e8-ab5b-42010a8e0035 100Gi RWO Delete Bound default/datadir-my-release-cockroachdb-0 standard 51s +pvc-64945b4f-f3f0-11e8-ab5b-42010a8e0035 100Gi RWO Delete Bound default/datadir-my-release-cockroachdb-1 standard 51s +pvc-649d920d-f3f0-11e8-ab5b-42010a8e0035 100Gi RWO Delete Bound default/datadir-my-release-cockroachdb-2 standard 51s +``` + +### Running in secure mode + +In order to set up a secure cockroachdb cluster set `tls.enabled` to `yes`/`true` + +There are 3 ways to configure a secure cluster, with this chart. This all relates to how the certificates are issued: + +* Self-signer (default) +* Cert-manager +* Manual + +#### Self-signer + +This is the default behaviour, and requires no configuration beyond setting certificate durations if user wants to set custom duration. + +If you are running in this mode, self-signed certificates are created by self-signed utility for the nodes and root client and are stored in a secret. +You can look for the certificates created: +```shell +kubectl get secrets +``` + +```shell +crdb-cockroachdb-ca-secret Opaque 2 23s +crdb-cockroachdb-client-secret kubernetes.io/tls 3 22s +crdb-cockroachdb-node-secret kubernetes.io/tls 3 23s +``` + + +#### Manual + +If you wish to supply the certificates to the nodes yourself set `tls.certs.provided` to `yes`/`true`. You may want to use this if you want to use a different certificate authority from the one being used by Kubernetes or if your Kubernetes cluster doesn't fully support certificate-signing requests. To use this, first set up your certificates and load them into your Kubernetes cluster as Secrets using the commands below: + +```shell +$ mkdir certs +$ mkdir my-safe-directory +$ cockroach cert create-ca --certs-dir=certs --ca-key=my-safe-directory/ca.key +$ cockroach cert create-client root --certs-dir=certs --ca-key=my-safe-directory/ca.key +$ kubectl create secret generic cockroachdb-root --from-file=certs +secret/cockroachdb-root created +$ cockroach cert create-node --certs-dir=certs --ca-key=my-safe-directory/ca.key localhost 127.0.0.1 my-release-cockroachdb-public my-release-cockroachdb-public.my-namespace my-release-cockroachdb-public.my-namespace.svc.cluster.local *.my-release-cockroachdb *.my-release-cockroachdb.my-namespace *.my-release-cockroachdb.my-namespace.svc.cluster.local +$ kubectl create secret generic cockroachdb-node --from-file=certs +secret/cockroachdb-node created +``` + +> Note: The subject alternative names are based on a release called `my-release` in the `my-namespace` namespace. Make sure they match the services created with the release during `helm install` + +If your certificates are stored in tls secrets such as secrets generated by cert-manager, the secret will contain files named: + +* `ca.crt` +* `tls.crt` +* `tls.key` + +Cockroachdb, however, expects the files to be named like this: + +* `ca.crt` +* `node.crt` +* `node.key` +* `client.root.crt` +* `client.root.key` + +By enabling `tls.certs.tlsSecret` the tls secrets are projected on to the correct filenames, when they are mounted to the cockroachdb pods. + +#### Cert-manager + +If you wish to supply certificates with [cert-manager][3], set + +* `tls.certs.certManager` to `yes`/`true` +* `tls.certs.certManagerIssuer` to an IssuerRef (as they appear in certificate resources) pointing to a clusterIssuer or issuer, you have set up in the cluster + +Example issuer: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: cockroachdb-ca + namespace: cockroachdb +data: + tls.crt: [BASE64 Encoded ca.crt] + tls.key: [BASE64 Encoded ca.key] +type: kubernetes.io/tls +--- +apiVersion: cert-manager.io/v1alpha3 +kind: Issuer +metadata: + name: cockroachdb-cert-issuer + namespace: cockroachdb +spec: + ca: + secretName: cockroachdb-ca +``` + +## Upgrading the cluster + +### Chart version 3.0.0 and after + +Launch a temporary interactive pod and start the built-in SQL client: + +```shell +kubectl run cockroachdb --rm -it \ +--image=cockroachdb/cockroach \ +--restart=Never \ +-- sql --insecure --host=my-release-cockroachdb-public +``` + +> If you are running in secure mode, you will have to provide a client certificate to the cluster in order to authenticate, so the above command will not work. See [here](https://github.com/cockroachdb/cockroach/blob/master/cloud/kubernetes/client-secure.yaml) for an example of how to set up an interactive SQL shell against a secure cluster or [here](https://github.com/cockroachdb/cockroach/blob/master/cloud/kubernetes/example-app-secure.yaml) for an example application connecting to a secure cluster. + +Set `cluster.preserve_downgrade_option`, where `$current_version` is the CockroachDB version currently running (e.g., `19.2`): + +```sql +> SET CLUSTER SETTING cluster.preserve_downgrade_option = '$current_version'; +``` + +Exit the shell and delete the temporary pod: + +```sql +> \q +``` + +Kick off the upgrade process by changing the new Docker image, where `$new_version` is the CockroachDB version to which you are upgrading: + +```shell +helm upgrade my-release cockroachdb/cockroachdb \ +--set image.tag=$new_version \ +--reuse-values +``` + +Kubernetes will carry out a safe [rolling upgrade](https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets) of your CockroachDB nodes one-by-one. Monitor the cluster's pods until all have been successfully restarted: + +```shell +kubectl get pods +``` + +``` +NAME READY STATUS RESTARTS AGE +my-release-cockroachdb-0 1/1 Running 0 2m +my-release-cockroachdb-1 1/1 Running 0 3m +my-release-cockroachdb-2 1/1 Running 0 3m +my-release-cockroachdb-3 0/1 ContainerCreating 0 25s +my-release-cockroachdb-init-nwjkh 0/1 ContainerCreating 0 6s +``` + +```shell +kubectl get pods \ +-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[0].image}{"\n"}' +``` + +``` +my-release-cockroachdb-0 cockroachdb/cockroach:v24.2.1 +my-release-cockroachdb-1 cockroachdb/cockroach:v24.2.1 +my-release-cockroachdb-2 cockroachdb/cockroach:v24.2.1 +my-release-cockroachdb-3 cockroachdb/cockroach:v24.2.1 +``` + +Resume normal operations. Once you are comfortable that the stability and performance of the cluster is what you'd expect post-upgrade, finalize the upgrade: + +```shell +kubectl run cockroachdb --rm -it \ +--image=cockroachdb/cockroach \ +--restart=Never \ +-- sql --insecure --host=my-release-cockroachdb-public +``` + +```sql +> RESET CLUSTER SETTING cluster.preserve_downgrade_option; +> \q +``` + +### Chart versions prior to 3.0.0 + +Due to a change in the label format in version 3.0.0 of this chart, upgrading requires that you delete the StatefulSet. Luckily there is a way to do it without actually deleting all the resources managed by the StatefulSet. Use the workaround below to upgrade from charts versions previous to 3.0.0: + +Get the new labels from the specs rendered by Helm: + +```shell +helm template -f deploy.vals.yml cockroachdb/cockroachdb -x templates/statefulset.yaml \ +| yq r - spec.template.metadata.labels +``` + +``` +app.kubernetes.io/name: cockroachdb +app.kubernetes.io/instance: my-release +app.kubernetes.io/component: cockroachdb +``` + +Place the new labels on all pods of the StatefulSet (change `my-release-cockroachdb-0` to the name of each pod): + +```shell +kubectl label pods my-release-cockroachdb-0 \ +app.kubernetes.io/name=cockroachdb \ +app.kubernetes.io/instance=my-release \ +app.kubernetes.io/component=cockroachdb +``` + +Delete the StatefulSet without deleting pods: + +```shell +kubectl delete statefulset my-release-cockroachdb --cascade=false +``` + +Verify that no pod is deleted and then upgrade as normal. A new StatefulSet will be created, taking over the management of the existing pods and upgrading them if needed. + +### See also + +For more information about upgrading a cluster to the latest major release of CockroachDB, see [Upgrade to CockroachDB](https://www.cockroachlabs.com/docs/stable/upgrade-cockroach-version.html). + +Note that there are sometimes backward-incompatible changes to SQL features between major CockroachDB releases. For details, see the [Upgrade Policy](https://www.cockroachlabs.com/docs/cockroachcloud/upgrade-policy). + +## Configuration + +The following table lists the configurable parameters of the CockroachDB chart and their default values. +For details see the [`values.yaml`](values.yaml) file. + +| Parameter | Description | Default | +| --------- | ----------- | ------- | +| `clusterDomain` | Cluster's default DNS domain | `cluster.local` | +| `conf.attrs` | CockroachDB node attributes | `[]` | +| `conf.cache` | Size of CockroachDB's in-memory cache | `25%` | +| `conf.cluster-name` | Name of CockroachDB cluster | `""` | +| `conf.disable-cluster-name-verification` | Disable CockroachDB cluster name verification | `no` | +| `conf.join` | List of already-existing CockroachDB instances | `[]` | +| `conf.max-disk-temp-storage` | Max storage capacity for temp data | `0` | +| `conf.max-offset` | Max allowed clock offset for CockroachDB cluster | `500ms` | +| `conf.max-sql-memory` | Max memory to use processing SQL querie | `25%` | +| `conf.locality` | Locality attribute for this deployment | `""` | +| `conf.single-node` | Disable CockroachDB clustering (standalone mode) | `no` | +| `conf.sql-audit-dir` | Directory for SQL audit log | `""` | +| `conf.port` | CockroachDB primary serving port in Pods | `26257` | +| `conf.http-port` | CockroachDB HTTP port in Pods | `8080` | +| `conf.path` | CockroachDB data directory mount path | `cockroach-data` | +| `conf.store.enabled` | Enable store configuration for CockroachDB | `false` | +| `conf.store.type` | CockroachDB storage type | `""` | +| `conf.store.size` | CockroachDB storage size | `""` | +| `conf.store.attrs` | CockroachDB storage attributes | `""` | +| `image.repository` | Container image name | `cockroachdb/cockroach` | +| `image.tag` | Container image tag | `v24.2.1` | +| `image.pullPolicy` | Container pull policy | `IfNotPresent` | +| `image.credentials` | `registry`, `user` and `pass` credentials to pull private image | `{}` | +| `statefulset.replicas` | StatefulSet replicas number | `3` | +| `statefulset.updateStrategy` | Update strategy for StatefulSet Pods | `{"type": "RollingUpdate"}` | +| `statefulset.podManagementPolicy` | `OrderedReady`/`Parallel` Pods creation/deletion order | `Parallel` | +| `statefulset.budget.maxUnavailable` | k8s PodDisruptionBudget parameter | `1` | +| `statefulset.args` | Extra command-line arguments | `[]` | +| `statefulset.env` | Extra env vars | `[]` | +| `statefulset.secretMounts` | Additional Secrets to mount at cluster members | `[]` | +| `statefulset.labels` | Additional labels of StatefulSet and its Pods | `{"app.kubernetes.io/component": "cockroachdb"}` | +| `statefulset.annotations` | Additional annotations of StatefulSet Pods | `{}` | +| `statefulset.nodeAffinity` | [Node affinity rules][2] of StatefulSet Pods | `{}` | +| `statefulset.podAffinity` | [Inter-Pod affinity rules][1] of StatefulSet Pods | `{}` | +| `statefulset.podAntiAffinity` | [Anti-affinity rules][1] of StatefulSet Pods | auto | +| `statefulset.podAntiAffinity.topologyKey` | The topologyKey for auto [anti-affinity rules][1] | `kubernetes.io/hostname` | +| `statefulset.podAntiAffinity.type` | Type of auto [anti-affinity rules][1] | `soft` | +| `statefulset.podAntiAffinity.weight` | Weight for `soft` auto [anti-affinity rules][1] | `100` | +| `statefulset.nodeSelector` | Node labels for StatefulSet Pods assignment | `{}` | +| `statefulset.priorityClassName` | [PriorityClassName][4] for StatefulSet Pods | `""` | +| `statefulset.tolerations` | Node taints to tolerate by StatefulSet Pods | `[]` | +| `statefulset.topologySpreadConstraints` | [Topology Spread Constraints rules][5] of StatefulSet Pods | auto | +| `statefulset.topologySpreadConstraints.maxSkew` | Degree to which Pods may be unevenly distributed | `1` | +| `statefulset.topologySpreadConstraints.topologyKey` | The key of node labels | `topology.kubernetes.io/zone` | +| `statefulset.topologySpreadConstraints.whenUnsatisfiable` | `ScheduleAnyway`/`DoNotSchedule` for unsatisfiable constraints | `ScheduleAnyway` | +| `statefulset.resources` | Resource requests and limits for StatefulSet Pods | `{}` | +| `statefulset.customLivenessProbe` | Custom Liveness probe | `{}` | +| `statefulset.customReadinessProbe` | Custom Rediness probe | `{}` | +| `service.ports.grpc.external.port` | CockroachDB primary serving port in Services | `26257` | +| `service.ports.grpc.external.name` | CockroachDB primary serving port name in Services | `grpc` | +| `service.ports.grpc.internal.port` | CockroachDB inter-communication port in Services | `26257` | +| `service.ports.grpc.internal.name` | CockroachDB inter-communication port name in Services | `grpc-internal` | +| `service.ports.http.port` | CockroachDB HTTP port in Services | `8080` | +| `service.ports.http.name` | CockroachDB HTTP port name in Services | `http` | +| `service.public.type` | Public Service type | `ClusterIP` | +| `service.public.labels` | Additional labels of public Service | `{"app.kubernetes.io/component": "cockroachdb"}` | +| `service.public.annotations` | Additional annotations of public Service | `{}` | +| `service.discovery.labels` | Additional labels of discovery Service | `{"app.kubernetes.io/component": "cockroachdb"}` | +| `service.discovery.annotations` | Additional annotations of discovery Service | `{}` | +| `ingress.enabled` | Enable ingress resource for CockroachDB | `false` | +| `ingress.labels` | Additional labels of Ingress | `{}` | +| `ingress.annotations` | Additional annotations of Ingress | `{}` | +| `ingress.paths` | Paths for the default host | `[/]` | +| `ingress.hosts` | CockroachDB Ingress hostnames | `[]` | +| `ingress.tls[0].hosts` | CockroachDB Ingress tls hostnames | `nil` | +| `ingress.tls[0].secretName` | CockroachDB Ingress tls secret name | `nil` | +| `prometheus.enabled` | Enable automatic monitoring of all instances when Prometheus is running | `true` | +| `serviceMonitor.enabled` | Create [ServiceMonitor](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/design.md#servicemonitor) Resource for scraping metrics using [PrometheusOperator](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md#prometheus-operator) | `false` | +| `serviceMonitor.labels` | Additional labels of ServiceMonitor | `{}` | +| `serviceMonitor.annotations` | Additional annotations of ServiceMonitor | `{}` | +| `serviceMonitor.interval` | ServiceMonitor scrape metrics interval | `10s` | +| `serviceMonitor.scrapeTimeout` | ServiceMonitor scrape timeout | `nil` | +| `serviceMonitor.tlsConfig` | Additional TLS configuration of ServiceMonitor | `{}` | +| `serviceMonitor.namespaced` | Limit ServiceMonitor to current namespace | `false` | +| `storage.hostPath` | Absolute path on host to store data | `""` | +| `storage.persistentVolume.enabled` | Whether to use PersistentVolume to store data | `yes` | +| `storage.persistentVolume.size` | PersistentVolume size | `100Gi` | +| `storage.persistentVolume.storageClass` | PersistentVolume class | `""` | +| `storage.persistentVolume.labels` | Additional labels of PersistentVolumeClaim | `{}` | +| `storage.persistentVolume.annotations` | Additional annotations of PersistentVolumeClaim | `{}` | +| `init.labels` | Additional labels of init Job and its Pod | `{"app.kubernetes.io/component": "init"}` | +| `init.jobAnnotations` | Additional annotations of the init Job itself | `{}` | +| `init.annotations` | Additional annotations of the Pod of init Job | `{}` | +| `init.affinity` | [Affinity rules][2] of init Job Pod | `{}` | +| `init.nodeSelector` | Node labels for init Job Pod assignment | `{}` | +| `init.tolerations` | Node taints to tolerate by init Job Pod | `[]` | +| `init.resources` | Resource requests and limits for the `cluster-init` container | `{}` | +| `tls.enabled` | Whether to run securely using TLS certificates | `no` | +| `tls.serviceAccount.create` | Whether to create a new RBAC service account | `yes` | +| `tls.serviceAccount.name` | Name of RBAC service account to use | `""` | +| `tls.copyCerts.image` | Image used in copy certs init container | `busybox` | +| `tls.copyCerts.resources` | Resource requests and limits for the `copy-certs` container | `{}` | +| `tls.certs.provided` | Bring your own certs scenario, i.e certificates are provided | `no` | +| `tls.certs.clientRootSecret` | If certs are provided, secret name for client root cert | `cockroachdb-root` | +| `tls.certs.nodeSecret` | If certs are provided, secret name for node cert | `cockroachdb-node` | +| `tls.certs.tlsSecret` | Own certs are stored in TLS secret | `no` | +| `tls.certs.selfSigner.enabled` | Whether cockroachdb should generate its own self-signed certs | `true` | +| `tls.certs.selfSigner.caProvided` | Bring your own CA scenario. This CA will be used to generate node and client cert | `false` | +| `tls.certs.selfSigner.caSecret` | If CA is provided, secret name for CA cert | `""` | +| `tls.certs.selfSigner.minimumCertDuration` | Minimum cert duration for all the certs, all certs duration will be validated against this duration | `624h` | +| `tls.certs.selfSigner.caCertDuration` | Duration of CA cert in hour | `43824h` | +| `tls.certs.selfSigner.caCertExpiryWindow` | Expiry window of CA cert means a window before actual expiry in which CA cert should be rotated | `648h` | +| `tls.certs.selfSigner.clientCertDuration` | Duration of client cert in hour | `672h | +| `tls.certs.selfSigner.clientCertExpiryWindow` | Expiry window of client cert means a window before actual expiry in which client cert should be rotated | `48h` | +| `tls.certs.selfSigner.nodeCertDuration` | Duration of node cert in hour | `8760h` | +| `tls.certs.selfSigner.nodeCertExpiryWindow` | Expiry window of node cert means a window before actual expiry in which node certs should be rotated | `168h` | +| `tls.certs.selfSigner.rotateCerts` | Whether to rotate the certs generate by cockroachdb | `true` | +| `tls.certs.selfSigner.readinessWait` | Wait time for each cockroachdb replica to become ready once it comes in running state. Only considered when rotateCerts is set to true | `30s` | +| `tls.certs.selfSigner.podUpdateTimeout` | Wait time for each cockroachdb replica to get to running state. Only considered when rotateCerts is set to true | `2m` | +| `tls.certs.certManager` | Provision certificates with cert-manager | `false` | +| `tls.certs.certManagerIssuer.group` | IssuerRef group to use when generating certificates | `cert-manager.io` | +| `tls.certs.certManagerIssuer.kind` | IssuerRef kind to use when generating certificates | `Issuer` | +| `tls.certs.certManagerIssuer.name` | IssuerRef name to use when generating certificates | `cockroachdb` | +| `tls.certs.certManagerIssuer.caCertDuration` | Duration of CA cert in hour | `43824h` | +| `tls.certs.certManagerIssuer.caCertExpiryWindow` | Expiry window of CA cert means a window before actual expiry in which CA cert should be rotated | `648h` | +| `tls.certs.certManagerIssuer.clientCertDuration` | Duration of client cert in hours | `672h` | +| `tls.certs.certManagerIssuer.clientCertExpiryWindow` | Expiry window of client cert means a window before actual expiry in which client cert should be rotated | `48h` | +| `tls.certs.certManagerIssuer.nodeCertDuration` | Duration of node cert in hours | `8760h` | +| `tls.certs.certManagerIssuer.nodeCertExpiryWindow` | Expiry window of node certificates means a window before actual expiry in which node certs should be rotated. | `168h` | +| `tls.selfSigner.image.repository` | Image to use for self signing TLS certificates | `cockroachlabs-helm-charts/cockroach-self-signer-cert`| +| `tls.selfSigner.image.tag` | Image tag to use for self signing TLS certificates | `0.1` | +| `tls.selfSigner.image.pullPolicy` | Self signing TLS certificates container pull policy | `IfNotPresent` | +| `tls.selfSigner.image.credentials` | `registry`, `user` and `pass` credentials to pull private image | `{}` | +| `networkPolicy.enabled` | Enable NetworkPolicy for CockroachDB's Pods | `no` | +| `networkPolicy.ingress.grpc` | Whitelist resources to access gRPC port of CockroachDB's Pods | `[]` | +| `networkPolicy.ingress.http` | Whitelist resources to access gRPC port of CockroachDB's Pods | `[]` | + + +Override the default parameters using the `--set key=value[,key=value]` argument to `helm install`. + +Alternatively, a YAML file that specifies custom values for the parameters can be provided while installing the chart. For example: + +```shell +helm install my-release -f my-values.yaml cockroachdb/cockroachdb +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Deep dive + +### Connecting to the CockroachDB cluster + +Once you've created the cluster, you can start talking to it by connecting to its `-public` Service. CockroachDB is PostgreSQL wire protocol compatible, so there's a [wide variety of supported clients](https://www.cockroachlabs.com/docs/install-client-drivers.html). As an example, we'll open up a SQL shell using CockroachDB's built-in shell and play around with it a bit, like this (likely needing to replace `my-release-cockroachdb-public` with the name of the `-public` Service that was created with your installed chart): + +```shell +kubectl run cockroach-client --rm -it \ +--image=cockroachdb/cockroach \ +--restart=Never \ +-- sql --insecure --host my-release-cockroachdb-public +``` + +``` +Waiting for pod default/cockroach-client to be running, status is Pending, +pod ready: false +If you don't see a command prompt, try pressing enter. +root@my-release-cockroachdb-public:26257> SHOW DATABASES; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| pg_catalog | +| system | ++--------------------+ +(3 rows) +root@my-release-cockroachdb-public:26257> CREATE DATABASE bank; +CREATE DATABASE +root@my-release-cockroachdb-public:26257> CREATE TABLE bank.accounts (id INT +PRIMARY KEY, balance DECIMAL); +CREATE TABLE +root@my-release-cockroachdb-public:26257> INSERT INTO bank.accounts VALUES +(1234, 10000.50); +INSERT 1 +root@my-release-cockroachdb-public:26257> SELECT * FROM bank.accounts; ++------+---------+ +| id | balance | ++------+---------+ +| 1234 | 10000.5 | ++------+---------+ +(1 row) +root@my-release-cockroachdb-public:26257> \q +Waiting for pod default/cockroach-client to terminate, status is Running +pod "cockroach-client" deleted +``` + +> If you are running in secure mode, you will have to provide a client certificate to the cluster in order to authenticate, so the above command will not work. See [here](https://github.com/cockroachdb/cockroach/blob/master/cloud/kubernetes/client-secure.yaml) for an example of how to set up an interactive SQL shell against a secure cluster or [here](https://github.com/cockroachdb/cockroach/blob/master/cloud/kubernetes/example-app-secure.yaml) for an example application connecting to a secure cluster. + +### Cluster health + +Because our pod spec includes regular health checks of the CockroachDB processes, simply running `kubectl get pods` and looking at the `STATUS` column is sufficient to determine the health of each instance in the cluster. + +If you want more detailed information about the cluster, the best place to look is the Admin UI. + +### Accessing the Admin UI + +If you want to see information about how the cluster is doing, you can try pulling up the CockroachDB Admin UI by port-forwarding from your local machine to one of the pods (replacing `my-release-cockroachdb-0` with the name of one of your pods: + +```shell +kubectl port-forward my-release-cockroachdb-0 8080 +``` + +You should then be able to access the Admin UI by visiting in your web browser. + +### Failover + +If any CockroachDB member fails, it is restarted or recreated automatically by the Kubernetes infrastructure, and will re-join the cluster automatically when it comes back up. You can test this scenario by killing any of the CockroachDB pods: + +```shell +kubectl delete pod my-release-cockroachdb-1 +``` + +```shell +kubectl get pods -l "app.kubernetes.io/instance=my-release,app.kubernetes.io/component=cockroachdb" +``` + +``` +NAME READY STATUS RESTARTS AGE +my-release-cockroachdb-0 1/1 Running 0 5m +my-release-cockroachdb-2 1/1 Running 0 5m +``` + +After a while: + +```shell +kubectl get pods -l "app.kubernetes.io/instance=my-release,app.kubernetes.io/component=cockroachdb" +``` + +``` +NAME READY STATUS RESTARTS AGE +my-release-cockroachdb-0 1/1 Running 0 5m +my-release-cockroachdb-1 1/1 Running 0 20s +my-release-cockroachdb-2 1/1 Running 0 5m +``` + +You can check the state of re-joining from the new pod's logs: + +```shell +kubectl logs my-release-cockroachdb-1 +``` + +``` +[...] +I161028 19:32:09.754026 1 server/node.go:586 [n1] node connected via gossip and +verified as part of cluster {"35ecbc27-3f67-4e7d-9b8f-27c31aae17d6"} +[...] +cockroachdb-0.my-release-cockroachdb.default.svc.cluster.local:26257 +build: beta-20161027-55-gd2d3c7f @ 2016/10/28 19:27:25 (go1.7.3) +admin: http://0.0.0.0:8080 +sql: +postgresql://root@my-release-cockroachdb-1.my-release-cockroachdb.default.svc.cluster.local:26257?sslmode=disable +logs: cockroach-data/logs +store[0]: path=cockroach-data +status: restarted pre-existing node +clusterID: {35ecbc27-3f67-4e7d-9b8f-27c31aae17d6} +nodeID: 2 +[...] +``` + +### NetworkPolicy + +To enable NetworkPolicy for CockroachDB, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin), and set `networkPolicy.enabled` to `yes`/`true`. + +For Kubernetes v1.5 & v1.6, you must also turn on NetworkPolicy by setting the `DefaultDeny` Namespace annotation. Note: this will enforce policy for _all_ pods in the Namespace: + +```shell +kubectl annotate namespace default "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}" +``` + +For more precise policy, set `networkPolicy.ingress.grpc` and `networkPolicy.ingress.http` rules. This will only allow pods that match the provided rules to connect to CockroachDB. + +### Scaling + +Scaling should be managed via the `helm upgrade` command. After resizing your cluster on your cloud environment (e.g., GKE or EKS), run the following command to add a pod. This assumes you scaled from 3 to 4 nodes: + +```shell +helm upgrade \ +my-release \ +cockroachdb/cockroachdb \ +--set statefulset.replicas=4 \ +--reuse-values +``` + +Note, that if you are running in secure mode (`tls.enabled` is `yes`/`true`) and increase the size of your cluster, you will also have to approve the CSR (certificate-signing request) of each new node (using `kubectl get csr` and `kubectl certificate approve`). + +[1]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity +[2]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity +[3]: https://cert-manager.io/ +[4]: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass +[5]: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/app-readme.md b/charts/cockroach-labs/cockroachdb/14.0.1/app-readme.md new file mode 100644 index 000000000..8fcc1fd6f --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/app-readme.md @@ -0,0 +1,9 @@ +# CockroachDB Chart + +CockroachDB is a Distributed SQL database that runs natively in Kubernetes. It gives you resilient, horizontal scale across multiple clouds with always-on availability and data partitioned by location. + +CockroachDB scales horizontally without reconfiguration or need for a massive architectural overhaul. Simply add a new node to the cluster and CockroachDB takes care of the underlying complexity. + + - Scale by simply adding new nodes to a CockroachDB cluster + - Automate balancing and distribution of ranges, not shards + - Optimize server utilization evenly across all nodes diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/NOTES.txt b/charts/cockroach-labs/cockroachdb/14.0.1/templates/NOTES.txt new file mode 100644 index 000000000..13b421f62 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/NOTES.txt @@ -0,0 +1,50 @@ +CockroachDB can be accessed via port {{ .Values.service.ports.grpc.external.port }} at the +following DNS name from within your cluster: + +{{ template "cockroachdb.fullname" . }}-public.{{ .Release.Namespace }}.svc.cluster.local + +Because CockroachDB supports the PostgreSQL wire protocol, you can connect to +the cluster using any available PostgreSQL client. + +{{- if not .Values.tls.enabled }} + +For example, you can open up a SQL shell to the cluster by running: + + kubectl run -it --rm cockroach-client \ + --image=cockroachdb/cockroach \ + --restart=Never \ + {{- if .Values.networkPolicy.enabled }} + --labels="{{ template "cockroachdb.fullname" . }}-client=true" \ + {{- end }} + --command -- \ + ./cockroach sql --insecure --host={{ template "cockroachdb.fullname" . }}-public.{{ .Release.Namespace }} + +From there, you can interact with the SQL shell as you would any other SQL +shell, confident that any data you write will be safe and available even if +parts of your cluster fail. +{{- else }} + +Note that because the cluster is running in secure mode, any client application +that you attempt to connect will either need to have a valid client certificate +or a valid username and password. +{{- end }} + +{{- if and (.Values.networkPolicy.enabled) (not (empty .Values.networkPolicy.ingress.grpc)) }} + +Note: Since NetworkPolicy is enabled, the only Pods allowed to connect to this +CockroachDB cluster are: + +1. Having the label: "{{ template "cockroachdb.fullname" . }}-client=true" + +2. Matching the following rules: {{- toYaml .Values.networkPolicy.ingress.grpc | nindent 0 }} +{{- end }} + +Finally, to open up the CockroachDB admin UI, you can port-forward from your +local machine into one of the instances in the cluster: + + kubectl port-forward -n {{ .Release.Namespace }} {{ template "cockroachdb.fullname" . }}-0 {{ index .Values.conf `http-port` | int64 }} + +Then you can access the admin UI at http{{ if .Values.tls.enabled }}s{{ end }}://localhost:{{ index .Values.conf `http-port` | int64 }}/ in your web browser. + +For more information on using CockroachDB, please see the project's docs at: +https://www.cockroachlabs.com/docs/ diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/_helpers.tpl b/charts/cockroach-labs/cockroachdb/14.0.1/templates/_helpers.tpl new file mode 100644 index 000000000..9ef769a70 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/_helpers.tpl @@ -0,0 +1,291 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "cockroachdb.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cockroachdb.fullname" -}} +{{- if .Values.fullnameOverride -}} + {{- .Values.fullnameOverride | trunc 56 | trimSuffix "-" -}} +{{- else -}} + {{- $name := default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- .Release.Name | trunc 56 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s" .Release.Name $name | trunc 56 | trimSuffix "-" -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified app name for cluster scope resource. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name with release namespace appended at the end. +*/}} +{{- define "cockroachdb.clusterfullname" -}} +{{- if .Values.fullnameOverride -}} + {{- printf "%s-%s" .Values.fullnameOverride .Release.Namespace | trunc 56 | trimSuffix "-" -}} +{{- else -}} + {{- $name := default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- printf "%s-%s" .Release.Name .Release.Namespace | trunc 56 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s-%s" .Release.Name $name .Release.Namespace | trunc 56 | trimSuffix "-" -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cockroachdb.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the ServiceAccount to use. +*/}} +{{- define "cockroachdb.serviceAccount.name" -}} +{{- if .Values.statefulset.serviceAccount.create -}} + {{- default (include "cockroachdb.fullname" .) .Values.statefulset.serviceAccount.name -}} +{{- else -}} + {{- default "default" .Values.statefulset.serviceAccount.name -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for NetworkPolicy. +*/}} +{{- define "cockroachdb.networkPolicy.apiVersion" -}} +{{- if semverCompare ">=1.4-0, <=1.7-0" .Capabilities.KubeVersion.Version -}} + {{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.7-0" .Capabilities.KubeVersion.Version -}} + {{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for StatefulSets +*/}} +{{- define "cockroachdb.statefulset.apiVersion" -}} +{{- if semverCompare "<1.12-0" .Capabilities.KubeVersion.Version -}} + {{- print "apps/v1beta1" -}} +{{- else -}} + {{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return CockroachDB store expression +*/}} +{{- define "cockroachdb.conf.store" -}} +{{- $isInMemory := eq (.Values.conf.store.type | toString) "mem" -}} +{{- $persistentSize := empty .Values.conf.store.size | ternary .Values.storage.persistentVolume.size .Values.conf.store.size -}} + +{{- $store := dict -}} +{{- $_ := set $store "type" ($isInMemory | ternary "type=mem" "") -}} +{{- $_ := set $store "path" ($isInMemory | ternary "" (print "path=" .Values.conf.path)) -}} +{{- $_ := set $store "size" (print "size=" ($isInMemory | ternary .Values.conf.store.size $persistentSize)) -}} +{{- $_ := set $store "attrs" (empty .Values.conf.store.attrs | ternary "" (print "attrs=" .Values.conf.store.attrs)) -}} + +{{ compact (values $store) | join "," }} +{{- end -}} + +{{/* +Define the default values for the certificate selfSigner inputs +*/}} +{{- define "selfcerts.fullname" -}} + {{- printf "%s-%s" (include "cockroachdb.fullname" .) "self-signer" | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{- define "rotatecerts.fullname" -}} + {{- printf "%s-%s" (include "cockroachdb.fullname" .) "rotate-self-signer" | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{- define "selfcerts.minimumCertDuration" -}} + {{- if .Values.tls.certs.selfSigner.minimumCertDuration -}} + {{- print (.Values.tls.certs.selfSigner.minimumCertDuration | trimSuffix "h") -}} + {{- else }} + {{- $minCertDuration := min (sub (.Values.tls.certs.selfSigner.clientCertDuration | trimSuffix "h" ) (.Values.tls.certs.selfSigner.clientCertExpiryWindow | trimSuffix "h")) (sub (.Values.tls.certs.selfSigner.nodeCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.nodeCertExpiryWindow | trimSuffix "h")) -}} + {{- print $minCertDuration -}} + {{- end }} +{{- end -}} + +{{/* +Define the cron schedules for certificate rotate jobs and converting from hours to valid cron string. +We assume that each month has 31 days, hence the cron job may run few days earlier in a year. In a cron schedule, +we can not set a cron of more than a year, hence we try to run the cron in such a way that the cron run comes to +as close possible to the expiry window. However, it is possible that cron may run earlier than the expiry window. +*/}} +{{- define "selfcerts.caRotateSchedule" -}} +{{- $tempHours := sub (.Values.tls.certs.selfSigner.caCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.caCertExpiryWindow | trimSuffix "h") -}} +{{- $days := "*" -}} +{{- $months := "*" -}} +{{- $hours := mod $tempHours 24 -}} +{{- if not (eq $hours $tempHours) -}} +{{- $tempDays := div $tempHours 24 -}} +{{- $days = mod $tempDays 31 -}} +{{- if not (eq $days $tempDays) -}} +{{- $days = add $days 1 -}} +{{- $tempMonths := div $tempDays 31 -}} +{{- $months = mod $tempMonths 12 -}} +{{- if not (eq $months $tempMonths) -}} +{{- $months = add $months 1 -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- if ne (toString $months) "*" -}} +{{- $months = printf "*/%s" (toString $months) -}} +{{- else -}} +{{- if ne (toString $days) "*" -}} +{{- $days = printf "*/%s" (toString $days) -}} +{{- else -}} +{{- if ne $hours 0 -}} +{{- $hours = printf "*/%s" (toString $hours) -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- printf "0 %s %s %s *" (toString $hours) (toString $days) (toString $months) -}} +{{- end -}} + +{{- define "selfcerts.clientRotateSchedule" -}} +{{- $tempHours := int64 (include "selfcerts.minimumCertDuration" .) -}} +{{- $days := "*" -}} +{{- $months := "*" -}} +{{- $hours := mod $tempHours 24 -}} +{{- if not (eq $hours $tempHours) -}} +{{- $tempDays := div $tempHours 24 -}} +{{- $days = mod $tempDays 31 -}} +{{- if not (eq $days $tempDays) -}} +{{- $days = add $days 1 -}} +{{- $tempMonths := div $tempDays 31 -}} +{{- $months = mod $tempMonths 12 -}} +{{- if not (eq $months $tempMonths) -}} +{{- $months = add $months 1 -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- if ne (toString $months) "*" -}} +{{- $months = printf "*/%s" (toString $months) -}} +{{- else -}} +{{- if ne (toString $days) "*" -}} +{{- $days = printf "*/%s" (toString $days) -}} +{{- else -}} +{{- if ne $hours 0 -}} +{{- $hours = printf "*/%s" (toString $hours) -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- printf "0 %s %s %s *" (toString $hours) (toString $days) (toString $months) -}} +{{- end -}} + +{{/* +Define the appropriate validations for the certificate selfSigner inputs +*/}} + +{{/* +Validate that if caProvided is true, then the caSecret must not be empty and secret must be present in the namespace. +*/}} +{{- define "cockroachdb.tls.certs.selfSigner.caProvidedValidation" -}} +{{- if .Values.tls.certs.selfSigner.caProvided -}} +{{- if eq "" .Values.tls.certs.selfSigner.caSecret -}} + {{ fail "CA secret can't be empty if caProvided is set to true" }} +{{- else -}} + {{- if not (lookup "v1" "Secret" .Release.Namespace .Values.tls.certs.selfSigner.caSecret) }} + {{ fail "CA secret is not present in the release namespace" }} + {{- end }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate that if caCertDuration or caCertExpiryWindow must not be empty and caCertExpiryWindow must be greater than +minimumCertDuration. +*/}} +{{- define "cockroachdb.tls.certs.selfSigner.caCertValidation" -}} +{{- if not .Values.tls.certs.selfSigner.caProvided -}} +{{- if or (not .Values.tls.certs.selfSigner.caCertDuration) (not .Values.tls.certs.selfSigner.caCertExpiryWindow) }} + {{ fail "CA cert duration or CA cert expiry window can not be empty" }} +{{- else }} +{{- if gt (int64 (include "selfcerts.minimumCertDuration" .)) (int64 (.Values.tls.certs.selfSigner.caCertExpiryWindow | trimSuffix "h")) -}} + {{ fail "CA cert expiration window should not be less than minimum Cert duration" }} +{{- end -}} +{{- if gt (int64 (include "selfcerts.minimumCertDuration" .)) (sub (.Values.tls.certs.selfSigner.caCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.caCertExpiryWindow | trimSuffix "h")) -}} + {{ fail "CA cert Duration minus CA cert expiration window should not be less than minimum Cert duration" }} +{{- end -}} +{{- end -}} +{{- end }} +{{- end -}} + +{{/* +Validate that if clientCertDuration must not be empty and it must be greater than minimumCertDuration. +*/}} +{{- define "cockroachdb.tls.certs.selfSigner.clientCertValidation" -}} +{{- if or (not .Values.tls.certs.selfSigner.clientCertDuration) (not .Values.tls.certs.selfSigner.clientCertExpiryWindow) }} + {{ fail "Client cert duration can not be empty" }} +{{- else }} +{{- if lt (sub (.Values.tls.certs.selfSigner.clientCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.clientCertExpiryWindow | trimSuffix "h")) (int64 (include "selfcerts.minimumCertDuration" .)) }} + {{ fail "Client cert duration minus client cert expiry window should not be less than minimum Cert duration" }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +Validate that nodeCertDuration must not be empty and nodeCertDuration minus nodeCertExpiryWindow must be greater than minimumCertDuration. +*/}} +{{- define "cockroachdb.tls.certs.selfSigner.nodeCertValidation" -}} +{{- if or (not .Values.tls.certs.selfSigner.nodeCertDuration) (not .Values.tls.certs.selfSigner.nodeCertExpiryWindow) }} + {{ fail "Node cert duration can not be empty" }} +{{- else }} +{{- if lt (sub (.Values.tls.certs.selfSigner.nodeCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.nodeCertExpiryWindow | trimSuffix "h")) (int64 (include "selfcerts.minimumCertDuration" .))}} + {{ fail "Node cert duration minus node cert expiry window should not be less than minimum Cert duration" }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +Validate that if user enabled tls, then either self-signed certificates or certificate manager is enabled +*/}} +{{- define "cockroachdb.tlsValidation" -}} +{{- if .Values.tls.enabled -}} +{{- if and .Values.tls.certs.selfSigner.enabled .Values.tls.certs.certManager -}} + {{ fail "Can not enable the self signed certificates and certificate manager at the same time" }} +{{- end -}} +{{- if and (not .Values.tls.certs.selfSigner.enabled) (not .Values.tls.certs.certManager) -}} + {{- if not .Values.tls.certs.provided -}} + {{ fail "You have to enable either self signed certificates or certificate manager, if you have enabled tls" }} + {{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} + + +{{- define "cockroachdb.tls.certs.selfSigner.validation" -}} +{{ include "cockroachdb.tls.certs.selfSigner.caProvidedValidation" . }} +{{ include "cockroachdb.tls.certs.selfSigner.caCertValidation" . }} +{{ include "cockroachdb.tls.certs.selfSigner.clientCertValidation" . }} +{{ include "cockroachdb.tls.certs.selfSigner.nodeCertValidation" . }} +{{- end -}} + +{{- define "cockroachdb.securityContext.versionValidation" }} +{{- /* Allow using `securityContext` for custom images. */}} +{{- if ne "cockroachdb/cockroach" .Values.image.repository -}} + {{ print true }} +{{- else -}} +{{- if semverCompare ">=22.1.2" .Values.image.tag -}} + {{ print true }} +{{- else -}} +{{- if semverCompare ">=21.2.13, <22.1.0" .Values.image.tag -}} + {{ print true }} +{{- else -}} + {{ print false }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/backendconfig.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/backendconfig.yaml new file mode 100644 index 000000000..2edc88619 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/backendconfig.yaml @@ -0,0 +1,21 @@ +{{- if .Values.iap.enabled }} +apiVersion: cloud.google.com/v1beta1 +kind: BackendConfig +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + iap: + enabled: true + oauthclientCredentials: + secretName: {{ template "cockroachdb.fullname" . }}.iap + timeoutSec: 120 +{{- end }} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.ca.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.ca.yaml new file mode 100644 index 000000000..4043fafb0 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.ca.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.certManager }} + {{- if .Values.tls.certs.certManagerIssuer.isSelfSignedIssuer }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ template "cockroachdb.fullname" . }}-ca-cert + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + duration: {{ .Values.tls.certs.certManagerIssuer.caCertDuration }} + renewBefore: {{ .Values.tls.certs.certManagerIssuer.caCertExpiryWindow }} + isCA: true + secretName: {{ .Values.tls.certs.caSecret }} + privateKey: + algorithm: ECDSA + size: 256 + commonName: root + subject: + organizations: + - Cockroach + issuerRef: + name: {{ .Values.tls.certs.certManagerIssuer.name }} + kind: {{ .Values.tls.certs.certManagerIssuer.kind }} + group: {{ .Values.tls.certs.certManagerIssuer.group }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.client.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.client.yaml new file mode 100644 index 000000000..dd0272f3e --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.client.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.certManager }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ template "cockroachdb.fullname" . }}-root-client + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + duration: {{ .Values.tls.certs.certManagerIssuer.clientCertDuration }} + renewBefore: {{ .Values.tls.certs.certManagerIssuer.clientCertExpiryWindow }} + usages: + - digital signature + - key encipherment + - client auth + privateKey: + algorithm: RSA + size: 2048 + commonName: root + subject: + organizations: + - Cockroach + secretName: {{ .Values.tls.certs.clientRootSecret }} + issuerRef: + {{- if .Values.tls.certs.certManagerIssuer.isSelfSignedIssuer }} + name: {{ template "cockroachdb.fullname" . }}-ca-issuer + kind: Issuer + group: cert-manager.io + {{- else }} + name: {{ .Values.tls.certs.certManagerIssuer.name }} + kind: {{ .Values.tls.certs.certManagerIssuer.kind }} + group: {{ .Values.tls.certs.certManagerIssuer.group }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.issuer.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.issuer.yaml new file mode 100644 index 000000000..5cf579ff9 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.issuer.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.certManager }} + {{- if .Values.tls.certs.certManagerIssuer.isSelfSignedIssuer }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ template "cockroachdb.fullname" . }}-ca-issuer + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ca: + secretName: {{ .Values.tls.certs.caSecret }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.node.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.node.yaml new file mode 100644 index 000000000..05e909d0b --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/certificate.node.yaml @@ -0,0 +1,50 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.certManager }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ template "cockroachdb.fullname" . }}-node + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + duration: {{ .Values.tls.certs.certManagerIssuer.nodeCertDuration }} + renewBefore: {{ .Values.tls.certs.certManagerIssuer.nodeCertExpiryWindow }} + usages: + - digital signature + - key encipherment + - server auth + - client auth + privateKey: + algorithm: RSA + size: 2048 + commonName: node + subject: + organizations: + - Cockroach + dnsNames: + - "localhost" + - "127.0.0.1" + - {{ printf "%s-public" (include "cockroachdb.fullname" .) | quote }} + - {{ printf "%s-public.%s" (include "cockroachdb.fullname" .) .Release.Namespace | quote }} + - {{ printf "%s-public.%s.svc.%s" (include "cockroachdb.fullname" .) .Release.Namespace .Values.clusterDomain | quote }} + - {{ printf "*.%s" (include "cockroachdb.fullname" .) | quote }} + - {{ printf "*.%s.%s" (include "cockroachdb.fullname" .) .Release.Namespace | quote }} + - {{ printf "*.%s.%s.svc.%s" (include "cockroachdb.fullname" .) .Release.Namespace .Values.clusterDomain | quote }} + secretName: {{ .Values.tls.certs.nodeSecret }} + issuerRef: + {{- if .Values.tls.certs.certManagerIssuer.isSelfSignedIssuer }} + name: {{ template "cockroachdb.fullname" . }}-ca-issuer + kind: Issuer + group: cert-manager.io + {{- else }} + name: {{ .Values.tls.certs.certManagerIssuer.name }} + kind: {{ .Values.tls.certs.certManagerIssuer.kind }} + group: {{ .Values.tls.certs.certManagerIssuer.group }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/clusterrole.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/clusterrole.yaml new file mode 100644 index 000000000..6b8a3dc5f --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/clusterrole.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.tls.enabled (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager) }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cockroachdb.clusterfullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: ["certificates.k8s.io"] + resources: ["certificatesigningrequests"] + verbs: ["create", "get", "watch"] +{{- end }} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/clusterrolebinding.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..3c18694ef --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/clusterrolebinding.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.tls.enabled (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager) }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cockroachdb.clusterfullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cockroachdb.clusterfullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "cockroachdb.serviceAccount.name" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/cronjob-ca-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/cronjob-ca-certSelfSigner.yaml new file mode 100644 index 000000000..903c42f76 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/cronjob-ca-certSelfSigner.yaml @@ -0,0 +1,46 @@ +{{- if and .Values.tls.enabled (and .Values.tls.certs.selfSigner.enabled (not .Values.tls.certs.selfSigner.caProvided)) }} + {{- if .Values.tls.certs.selfSigner.rotateCerts }} + {{- if .Capabilities.APIVersions.Has "batch/v1/CronJob" }} +apiVersion: batch/v1 + {{- else }} +apiVersion: batch/v1beta1 + {{- end }} +kind: CronJob +metadata: + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +spec: + schedule: {{ template "selfcerts.caRotateSchedule" . }} + jobTemplate: + spec: + backoffLimit: 1 + template: + spec: + restartPolicy: Never + containers: + - name: cert-rotate-job + image: "{{ .Values.tls.selfSigner.image.registry }}/{{ .Values.tls.selfSigner.image.repository }}:{{ .Values.tls.selfSigner.image.tag }}" + imagePullPolicy: "{{ .Values.tls.selfSigner.image.pullPolicy }}" + args: + - rotate + - --ca + - --ca-duration={{ .Values.tls.certs.selfSigner.caCertDuration }} + - --ca-expiry={{ .Values.tls.certs.selfSigner.caCertExpiryWindow }} + - --ca-cron={{ template "selfcerts.caRotateSchedule" . }} + - --readiness-wait={{ .Values.tls.certs.selfSigner.readinessWait }} + - --pod-update-timeout={{ .Values.tls.certs.selfSigner.podUpdateTimeout }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + - name: NAMESPACE + value: {{ .Release.Namespace }} + - name: CLUSTER_DOMAIN + value: {{ .Values.clusterDomain}} + serviceAccountName: {{ template "rotatecerts.fullname" . }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/cronjob-client-node-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/cronjob-client-node-certSelfSigner.yaml new file mode 100644 index 000000000..5c9f6d992 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/cronjob-client-node-certSelfSigner.yaml @@ -0,0 +1,53 @@ +{{- if and .Values.tls.certs.selfSigner.enabled .Values.tls.certs.selfSigner.rotateCerts }} + {{- if .Capabilities.APIVersions.Has "batch/v1/CronJob" }} +apiVersion: batch/v1 + {{- else }} +apiVersion: batch/v1beta1 + {{- end }} +kind: CronJob +metadata: + name: {{ template "rotatecerts.fullname" . }}-client + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +spec: + schedule: {{ template "selfcerts.clientRotateSchedule" . }} + jobTemplate: + spec: + backoffLimit: 1 + template: + spec: + restartPolicy: Never + containers: + - name: cert-rotate-job + image: "{{ .Values.tls.selfSigner.image.registry }}/{{ .Values.tls.selfSigner.image.repository }}:{{ .Values.tls.selfSigner.image.tag }}" + imagePullPolicy: "{{ .Values.tls.selfSigner.image.pullPolicy }}" + args: + - rotate + {{- if .Values.tls.certs.selfSigner.caProvided }} + - --ca-secret={{ .Values.tls.certs.selfSigner.caSecret }} + {{- else }} + - --ca-duration={{ .Values.tls.certs.selfSigner.caCertDuration }} + - --ca-expiry={{ .Values.tls.certs.selfSigner.caCertExpiryWindow }} + {{- end }} + - --client + - --client-duration={{ .Values.tls.certs.selfSigner.clientCertDuration }} + - --client-expiry={{ .Values.tls.certs.selfSigner.clientCertExpiryWindow }} + - --node + - --node-duration={{ .Values.tls.certs.selfSigner.nodeCertDuration }} + - --node-expiry={{ .Values.tls.certs.selfSigner.nodeCertExpiryWindow }} + - --node-client-cron={{ template "selfcerts.clientRotateSchedule" . }} + - --readiness-wait={{ .Values.tls.certs.selfSigner.readinessWait }} + - --pod-update-timeout={{ .Values.tls.certs.selfSigner.podUpdateTimeout }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + - name: NAMESPACE + value: {{ .Release.Namespace }} + - name: CLUSTER_DOMAIN + value: {{ .Values.clusterDomain}} + serviceAccountName: {{ template "rotatecerts.fullname" . }} + {{- end}} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/ingress.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/ingress.yaml new file mode 100644 index 000000000..2fa6373c8 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/ingress.yaml @@ -0,0 +1,90 @@ +{{- if .Values.ingress.enabled -}} +{{- $paths := .Values.ingress.paths -}} +{{- $ports := .Values.service.ports -}} +{{- $fullName := include "cockroachdb.fullname" . -}} +{{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} +apiVersion: networking.k8s.io/v1 +{{- else if $.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/Ingress" }} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: +{{- if or .Values.ingress.annotations .Values.iap.enabled }} + annotations: + {{- range $key, $value := .Values.ingress.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .Values.iap.enabled }} + kubernetes.io/ingress.class: "gce" + kubernetes.io/ingress.allow-http: "false" + {{- end }} +{{- end }} + name: {{ $fullName }}-ingress + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ $.Release.Name | quote }} + app.kubernetes.io/managed-by: {{ $.Release.Service | quote }} +{{- if .Values.ingress.labels }} +{{- toYaml .Values.ingress.labels | nindent 4 }} +{{- end }} +spec: + rules: + {{- if .Values.ingress.hosts }} + {{- range $host := .Values.ingress.hosts }} + - host: {{ $host }} + http: + paths: + {{- range $path := $paths }} + - path: {{ $path | quote }} + {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} + {{- if $.Values.iap.enabled }} + pathType: ImplementationSpecific + {{- else }} + pathType: Prefix + {{- end }} + {{- end }} + backend: + {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} + service: + name: {{ $fullName }}-public + port: + name: {{ $ports.http.name | quote }} + {{- else }} + serviceName: {{ $fullName }}-public + servicePort: {{ $ports.http.name | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- else }} + - http: + paths: + {{- range $path := $paths }} + - path: {{ $path | quote }} + {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} + {{- if $.Values.iap.enabled }} + pathType: ImplementationSpecific + {{- else }} + pathType: Prefix + {{- end }} + {{- end }} + backend: + {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} + service: + name: {{ $fullName }}-public + port: + name: {{ $ports.http.name | quote }} + {{- else }} + serviceName: {{ $fullName }}-public + servicePort: {{ $ports.http.name | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: +{{- toYaml .Values.ingress.tls | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/job-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/job-certSelfSigner.yaml new file mode 100644 index 000000000..7242a68b3 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/job-certSelfSigner.yaml @@ -0,0 +1,83 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "4" + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +spec: + template: + metadata: + name: {{ template "selfcerts.fullname" . }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.tls.selfSigner.annotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if and .Values.tls.certs.selfSigner.securityContext.enabled }} + securityContext: + seccompProfile: + type: "RuntimeDefault" + runAsGroup: 1000 + runAsUser: 1000 + fsGroup: 1000 + runAsNonRoot: true + {{- end }} + restartPolicy: Never + {{- if or .Values.tls.selfSigner.nodeAffinity }} + affinity: + {{- with .Values.tls.selfSigner.nodeAffinity }} + nodeAffinity: {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- with .Values.tls.selfSigner.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tls.selfSigner.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cert-generate-job + image: "{{ .Values.tls.selfSigner.image.registry }}/{{ .Values.tls.selfSigner.image.repository }}:{{ .Values.tls.selfSigner.image.tag }}" + imagePullPolicy: "{{ .Values.tls.selfSigner.image.pullPolicy }}" + args: + - generate + {{- if .Values.tls.certs.selfSigner.caProvided }} + - --ca-secret={{ .Values.tls.certs.selfSigner.caSecret }} + {{- else }} + - --ca-duration={{ .Values.tls.certs.selfSigner.caCertDuration }} + - --ca-expiry={{ .Values.tls.certs.selfSigner.caCertExpiryWindow }} + {{- end }} + - --client-duration={{ .Values.tls.certs.selfSigner.clientCertDuration }} + - --client-expiry={{ .Values.tls.certs.selfSigner.clientCertExpiryWindow }} + - --node-duration={{ .Values.tls.certs.selfSigner.nodeCertDuration }} + - --node-expiry={{ .Values.tls.certs.selfSigner.nodeCertExpiryWindow }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + - name: NAMESPACE + value: {{ .Release.Namespace | quote }} + - name: CLUSTER_DOMAIN + value: {{ .Values.clusterDomain}} + {{- if and .Values.tls.certs.selfSigner.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + {{- end }} + serviceAccountName: {{ template "selfcerts.fullname" . }} +{{- end}} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/job-cleaner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/job-cleaner.yaml new file mode 100644 index 000000000..5b6dc52f7 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/job-cleaner.yaml @@ -0,0 +1,55 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "selfcerts.fullname" . }}-cleaner + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +spec: + backoffLimit: 1 + template: + metadata: + name: {{ template "selfcerts.fullname" . }}-cleaner + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + spec: + {{- if and .Values.tls.certs.selfSigner.securityContext.enabled }} + securityContext: + seccompProfile: + type: "RuntimeDefault" + runAsGroup: 1000 + runAsUser: 1000 + fsGroup: 1000 + runAsNonRoot: true + {{- end }} + restartPolicy: Never + containers: + - name: cleaner + image: "{{ .Values.tls.selfSigner.image.registry }}/{{ .Values.tls.selfSigner.image.repository }}:{{ .Values.tls.selfSigner.image.tag }}" + imagePullPolicy: "{{ .Values.tls.selfSigner.image.pullPolicy }}" + args: + - cleanup + - --namespace={{ .Release.Namespace }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + {{- if and .Values.tls.certs.selfSigner.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + {{- end }} + serviceAccountName: {{ template "rotatecerts.fullname" . }} +{{- end}} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/job.init.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/job.init.yaml new file mode 100644 index 000000000..a4f498a15 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/job.init.yaml @@ -0,0 +1,296 @@ +{{ $isClusterInitEnabled := and (eq (len .Values.conf.join) 0) (not (index .Values.conf `single-node`)) }} +{{ $isDatabaseProvisioningEnabled := .Values.init.provisioning.enabled }} +{{- if or $isClusterInitEnabled $isDatabaseProvisioningEnabled }} + {{ template "cockroachdb.tlsValidation" . }} +kind: Job +apiVersion: batch/v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}-init + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.init.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-delete-policy: before-hook-creation + {{- with .Values.init.jobAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + template: + metadata: + labels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.init.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.init.annotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if eq (include "cockroachdb.securityContext.versionValidation" .) "true" }} + {{- if and .Values.init.securityContext.enabled }} + securityContext: + seccompProfile: + type: "RuntimeDefault" + runAsGroup: 1000 + runAsUser: 1000 + fsGroup: 1000 + runAsNonRoot: true + {{- end }} + {{- end }} + restartPolicy: OnFailure + terminationGracePeriodSeconds: 300 + {{- if or .Values.image.credentials (and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager)) }} + imagePullSecrets: + {{- if .Values.image.credentials }} + - name: {{ template "cockroachdb.fullname" . }}.db.registry + {{- end }} + {{- if and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager) }} + - name: {{ template "cockroachdb.fullname" . }}.self-signed-certs.registry + {{- end }} + {{- end }} + serviceAccountName: {{ template "cockroachdb.serviceAccount.name" . }} + {{- if .Values.tls.enabled }} + initContainers: + - name: copy-certs + image: {{ .Values.tls.copyCerts.image | quote }} + imagePullPolicy: {{ .Values.tls.selfSigner.image.pullPolicy | quote }} + command: + - /bin/sh + - -c + - "cp -f /certs/* /cockroach-certs/; chmod 0400 /cockroach-certs/*.key" + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if and .Values.init.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + {{- end }} + volumeMounts: + - name: client-certs + mountPath: /cockroach-certs/ + - name: certs-secret + mountPath: /certs/ + {{- with .Values.tls.copyCerts.resources }} + resources: {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- with .Values.init.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.init.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.init.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cluster-init + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + # Run the command in an `while true` loop because this Job is bound + # to come up before the CockroachDB Pods (due to the time needed to + # get PersistentVolumes attached to Nodes), and sleeping 5 seconds + # between attempts is much better than letting the Pod fail when + # the init command does and waiting out Kubernetes' non-configurable + # exponential back-off for Pod restarts. + # Command completes either when cluster initialization succeeds, + # or when cluster has been initialized already. + command: + - /bin/bash + - -c + - >- + {{- if $isClusterInitEnabled }} + initCluster() { + while true; do + local output=$( + set -x; + + /cockroach/cockroach init \ + {{- if .Values.tls.enabled }} + --certs-dir=/cockroach-certs/ \ + {{- else }} + --insecure \ + {{- end }} + {{- with index .Values.conf "cluster-name" }} + --cluster-name={{.}} \ + {{- end }} + --host={{ template "cockroachdb.fullname" . }}-0.{{ template "cockroachdb.fullname" . -}} + :{{ .Values.service.ports.grpc.internal.port | int64 }} \ + 2>&1); + + local exitCode="$?"; + echo $output; + + if [[ "$output" =~ .*"Cluster successfully initialized".* || "$output" =~ .*"cluster has already been initialized".* ]]; then + break; + fi + + echo "Cluster is not ready to be initialized, retrying in 5 seconds" + sleep 5; + done + } + + initCluster; + {{- end }} + + {{- if $isDatabaseProvisioningEnabled }} + provisionCluster() { + while true; do + /cockroach/cockroach sql \ + {{- if .Values.tls.enabled }} + --certs-dir=/cockroach-certs/ \ + {{- else }} + --insecure \ + {{- end }} + --host={{ template "cockroachdb.fullname" . }}-0.{{ template "cockroachdb.fullname" . -}} + :{{ .Values.service.ports.grpc.internal.port | int64 }} \ + --execute=" + {{- range $clusterSetting, $clusterSettingValue := .Values.init.provisioning.clusterSettings }} + SET CLUSTER SETTING {{ $clusterSetting }} = '${{ $clusterSetting | replace "." "_" }}_CLUSTER_SETTING'; + {{- end }} + + {{- range $user := .Values.init.provisioning.users }} + CREATE USER IF NOT EXISTS {{ $user.name }} WITH + {{- if $user.password }} + PASSWORD '${{ $user.name }}_PASSWORD' + {{- else }} + PASSWORD null + {{- end }} + {{ join " " $user.options }} + ; + {{- end }} + + {{- range $database := .Values.init.provisioning.databases }} + CREATE DATABASE IF NOT EXISTS {{ $database.name }} + {{- if $database.options }} + {{ join " " $database.options }} + {{- end }} + ; + + {{- range $owner := $database.owners }} + GRANT ALL ON DATABASE {{ $database.name }} TO {{ $owner }}; + {{- end }} + + {{- range $owner := $database.owners_with_grant_option }} + GRANT ALL ON DATABASE {{ $database.name }} TO {{ $owner }} WITH GRANT OPTION; + {{- end }} + + {{- if $database.backup }} + CREATE SCHEDULE IF NOT EXISTS {{ $database.name }}_scheduled_backup + FOR BACKUP DATABASE {{ $database.name }} INTO '{{ $database.backup.into }}' + + {{- if $database.backup.options }} + WITH {{ join "," $database.backup.options }} + {{- end }} + RECURRING '{{ $database.backup.recurring }}' + {{- if $database.backup.fullBackup }} + FULL BACKUP '{{ $database.backup.fullBackup }}' + {{- else }} + FULL BACKUP ALWAYS + {{- end }} + + {{- if and $database.backup.schedule $database.backup.schedule.options }} + WITH SCHEDULE OPTIONS {{ join "," $database.backup.schedule.options }} + {{- end }} + ; + {{- end }} + {{- end }} + " + &>/dev/null; + + local exitCode="$?"; + + if [[ "$exitCode" -eq "0" ]] + then break; + fi + + sleep 5; + done + + echo "Provisioning completed successfully"; + } + + provisionCluster; + {{- end }} + env: + {{- $secretName := printf "%s-init" (include "cockroachdb.fullname" .) }} + {{- range $user := .Values.init.provisioning.users }} + {{- if $user.password }} + - name: {{ $user.name }}_PASSWORD + valueFrom: + secretKeyRef: + name: {{ $secretName }} + key: {{ $user.name }}-password + {{- end }} + {{- end }} + {{- range $clusterSetting, $clusterSettingValue := .Values.init.provisioning.clusterSettings }} + {{- if $clusterSettingValue }} + - name: {{ $clusterSetting | replace "." "_" }}_CLUSTER_SETTING + valueFrom: + secretKeyRef: + name: {{ $secretName }} + key: {{ $clusterSetting | replace "." "-" }}-cluster-setting + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + volumeMounts: + - name: client-certs + mountPath: /cockroach-certs/ + {{- end }} + {{- with .Values.init.resources }} + resources: {{- toYaml . | nindent 12 }} + {{- end }} + {{- if and .Values.init.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + {{- end }} + {{- if .Values.tls.enabled }} + volumes: + - name: client-certs + emptyDir: {} + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} + - name: certs-secret + {{- if or .Values.tls.certs.tlsSecret .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} + projected: + sources: + - secret: + {{- if .Values.tls.certs.selfSigner.enabled }} + name: {{ template "cockroachdb.fullname" . }}-client-secret + {{ else }} + name: {{ .Values.tls.certs.clientRootSecret }} + {{ end -}} + items: + - key: ca.crt + path: ca.crt + mode: 0400 + - key: tls.crt + path: client.root.crt + mode: 0400 + - key: tls.key + path: client.root.key + mode: 0400 + {{- else }} + secret: + secretName: {{ .Values.tls.certs.clientRootSecret }} + defaultMode: 0400 + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/networkpolicy.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/networkpolicy.yaml new file mode 100644 index 000000000..d41afa32b --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/networkpolicy.yaml @@ -0,0 +1,59 @@ +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ template "cockroachdb.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "cockroachdb.serviceAccount.name" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + ingress: + - ports: + - port: grpc + {{- with .Values.networkPolicy.ingress.grpc }} + from: + # Allow connections via custom rules. + {{- toYaml . | nindent 8 }} + # Allow client connection via pre-considered label. + - podSelector: + matchLabels: + {{ template "cockroachdb.fullname" . }}-client: "true" + # Allow other CockroachDBs to connect to form a cluster. + - podSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 14 }} + {{- end }} + {{- if gt (.Values.statefulset.replicas | int64) 1 }} + # Allow init Job to connect to bootstrap a cluster. + - podSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.init.labels }} + {{- toYaml . | nindent 14 }} + {{- end }} + {{- end }} + {{- end }} + # Allow connections to admin UI and for Prometheus. + - ports: + - port: http + {{- with .Values.networkPolicy.ingress.http }} + from: {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/poddisruptionbudget.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/poddisruptionbudget.yaml new file mode 100644 index 000000000..f707e4054 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/poddisruptionbudget.yaml @@ -0,0 +1,26 @@ +kind: PodDisruptionBudget +{{- if or (.Capabilities.APIVersions.Has "policy/v1") (semverCompare ">=1.21-0" .Capabilities.KubeVersion.Version) }} +apiVersion: policy/v1 +{{- else }} +apiVersion: policy/v1beta1 +{{- end }} +metadata: + name: {{ template "cockroachdb.fullname" . }}-budget + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + maxUnavailable: {{ .Values.statefulset.budget.maxUnavailable | int64 }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/role-certRotateSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/role-certRotateSelfSigner.yaml new file mode 100644 index 000000000..f0e2b90ce --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/role-certRotateSelfSigner.yaml @@ -0,0 +1,27 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "update", "delete"] + - apiGroups: ["apps"] + resources: ["statefulsets"] + verbs: ["get"] + resourceNames: + - {{ template "cockroachdb.fullname" . }} + - apiGroups: [""] + resources: ["pods"] + verbs: ["delete", "get"] +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/role-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/role-certSelfSigner.yaml new file mode 100644 index 000000000..1cbaab3dd --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/role-certSelfSigner.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "2" + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "update", "delete"] + - apiGroups: ["apps"] + resources: ["statefulsets"] + verbs: ["get"] + resourceNames: + - {{ template "cockroachdb.fullname" . }} + - apiGroups: [""] + resources: ["pods"] + verbs: ["delete", "get"] +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/role.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/role.yaml new file mode 100644 index 000000000..ebe5ce8ae --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/role.yaml @@ -0,0 +1,23 @@ +{{- if .Values.tls.enabled }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: [""] + resources: ["secrets"] + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager }} + verbs: ["get"] + {{- else }} + verbs: ["create", "get"] + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding-certRotateSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding-certRotateSelfSigner.yaml new file mode 100644 index 000000000..c1a45f797 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding-certRotateSelfSigner.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "rotatecerts.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding-certSelfSigner.yaml new file mode 100644 index 000000000..5725d02a4 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding-certSelfSigner.yaml @@ -0,0 +1,29 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "3" + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "selfcerts.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding.yaml new file mode 100644 index 000000000..00d9f9a55 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/rolebinding.yaml @@ -0,0 +1,23 @@ +{{- if .Values.tls.enabled }} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cockroachdb.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "cockroachdb.serviceAccount.name" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.backendconfig.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.backendconfig.yaml new file mode 100644 index 000000000..61103060a --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.backendconfig.yaml @@ -0,0 +1,25 @@ +{{- if .Values.iap.enabled }} +kind: Secret +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}.iap + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if eq "" .Values.iap.clientId }} + {{ fail "iap.clientID can't be empty if iap.enabled is set to true" }} + {{- end }} + client_id: {{ .Values.iap.clientId | b64enc }} + {{- if eq "" .Values.iap.clientSecret }} + {{ fail "iap.clientSecret can't be empty if iap.enabled is set to true" }} + {{- end }} + client_secret: {{ .Values.iap.clientSecret | b64enc }} +{{- end }} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.logconfig.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.logconfig.yaml new file mode 100644 index 000000000..40b929ae7 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.logconfig.yaml @@ -0,0 +1,19 @@ +{{- if .Values.conf.log.enabled }} +kind: Secret +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}-log-config + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +type: Opaque +stringData: + log-config.yaml: | + {{- toYaml .Values.conf.log.config | nindent 4 }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.registry.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.registry.yaml new file mode 100644 index 000000000..a054069fb --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/secret.registry.yaml @@ -0,0 +1,23 @@ +{{- range $name, $cred := dict "db" (.Values.image.credentials) "init-certs" (.Values.tls.selfSigner.image.credentials) }} +{{- if not (empty $cred) }} +{{- if or (and (eq $name "init-certs") $.Values.tls.enabled) (ne $name "init-certs") }} +--- +kind: Secret +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" $ }}.{{ $name }}.registry + namespace: {{ $.Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" $ }} + app.kubernetes.io/name: {{ template "cockroachdb.name" $ }} + app.kubernetes.io/instance: {{ $.Release.Name | quote }} + app.kubernetes.io/managed-by: {{ $.Release.Service | quote }} + {{- with $.Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +type: kubernetes.io/dockerconfigjson +data: + .dockerconfigjson: {{ printf `{"auths":{%s:{"auth":"%s"}}}` ($cred.registry | quote) (printf "%s:%s" $cred.username $cred.password | b64enc) | b64enc | quote }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/secrets.init.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/secrets.init.yaml new file mode 100644 index 000000000..4d13a35ff --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/secrets.init.yaml @@ -0,0 +1,20 @@ +{{- if .Values.init.provisioning.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "cockroachdb.fullname" . }}-init + namespace: {{ .Release.Namespace | quote }} +type: Opaque +stringData: + +{{- range $user := .Values.init.provisioning.users }} +{{- if $user.password }} + {{ $user.name }}-password: {{ $user.password | quote }} +{{- end }} +{{- end }} + +{{- range $clusterSetting, $clusterSettingValue := .Values.init.provisioning.clusterSettings }} + {{ $clusterSetting | replace "." "-" }}-cluster-setting: {{ $clusterSettingValue | quote }} +{{- end }} + +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/service.discovery.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/service.discovery.yaml new file mode 100644 index 000000000..8fe2a427a --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/service.discovery.yaml @@ -0,0 +1,64 @@ +# This service only exists to create DNS entries for each pod in +# the StatefulSet such that they can resolve each other's IP addresses. +# It does not create a load-balanced ClusterIP and should not be used directly +# by clients in most circumstances. +kind: Service +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.service.discovery.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + # Use this annotation in addition to the actual field below because the + # annotation will stop being respected soon, but the field is broken in + # some versions of Kubernetes: + # https://github.com/kubernetes/kubernetes/issues/58662 + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" + # Enable automatic monitoring of all instances when Prometheus is running + # in the cluster. + {{- if .Values.prometheus.enabled }} + prometheus.io/scrape: "true" + prometheus.io/path: _status/vars + prometheus.io/port: {{ .Values.service.ports.http.port | quote }} + {{- end }} + {{- with .Values.service.discovery.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + clusterIP: None + # We want all Pods in the StatefulSet to have their addresses published for + # the sake of the other CockroachDB Pods even before they're ready, since they + # have to be able to talk to each other in order to become ready. + publishNotReadyAddresses: true + ports: + {{- $ports := .Values.service.ports }} + # The main port, served by gRPC, serves Postgres-flavor SQL, inter-node + # traffic and the CLI. + - name: {{ $ports.grpc.external.name | quote }} + port: {{ $ports.grpc.external.port | int64 }} + targetPort: grpc + {{- if ne ($ports.grpc.internal.port | int64) ($ports.grpc.external.port | int64) }} + - name: {{ $ports.grpc.internal.name | quote }} + port: {{ $ports.grpc.internal.port | int64 }} + targetPort: grpc + {{- end }} + # The secondary port serves the UI as well as health and debug endpoints. + - name: {{ $ports.http.name | quote }} + port: {{ $ports.http.port | int64 }} + targetPort: http + selector: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/service.public.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/service.public.yaml new file mode 100644 index 000000000..251e9ab08 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/service.public.yaml @@ -0,0 +1,55 @@ +# This Service is meant to be used by clients of the database. +# It exposes a ClusterIP that will automatically load balance connections +# to the different database Pods. +kind: Service +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}-public + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.service.public.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if or .Values.service.public.annotations .Values.tls.enabled .Values.iap.enabled }} + annotations: + {{- with .Values.service.public.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.tls.enabled }} + service.alpha.kubernetes.io/app-protocols: '{"http":"HTTPS"}' + {{- end }} + {{- if .Values.iap.enabled }} + beta.cloud.google.com/backend-config: '{"default": "{{ template "cockroachdb.fullname" . }}"}' + {{- end }} + {{- end }} +spec: + type: {{ .Values.service.public.type | quote }} + ports: + {{- $ports := .Values.service.ports }} + # The main port, served by gRPC, serves Postgres-flavor SQL, inter-node + # traffic and the CLI. + - name: {{ $ports.grpc.external.name | quote }} + port: {{ $ports.grpc.external.port | int64 }} + targetPort: grpc + {{- if ne ($ports.grpc.internal.port | int64) ($ports.grpc.external.port | int64) }} + - name: {{ $ports.grpc.internal.name | quote }} + port: {{ $ports.grpc.internal.port | int64 }} + targetPort: grpc + {{- end }} + # The secondary port serves the UI as well as health and debug endpoints. + - name: {{ $ports.http.name | quote }} + port: {{ $ports.http.port | int64 }} + targetPort: http + selector: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceMonitor.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceMonitor.yaml new file mode 100644 index 000000000..42f2390b4 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceMonitor.yaml @@ -0,0 +1,54 @@ +{{- $serviceMonitor := .Values.serviceMonitor -}} +{{- $ports := .Values.service.ports -}} +{{- if $serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- if $serviceMonitor.labels }} + {{- toYaml $serviceMonitor.labels | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if $serviceMonitor.annotations }} + annotations: + {{- toYaml $serviceMonitor.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.service.discovery.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + namespaceSelector: + {{- if $serviceMonitor.namespaced }} + matchNames: + - {{ .Release.Namespace }} + {{- else }} + any: true + {{- end }} + endpoints: + - port: {{ $ports.http.name | quote }} + path: /_status/vars + {{- if $serviceMonitor.interval }} + interval: {{ $serviceMonitor.interval }} + {{- end }} + {{- if $serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ $serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.serviceMonitor.tlsConfig }} + tlsConfig: {{ toYaml .Values.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount-certRotateSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount-certRotateSelfSigner.yaml new file mode 100644 index 000000000..a27cba921 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount-certRotateSelfSigner.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} + {{ template "cockroachdb.tls.certs.selfSigner.validation" . }} +kind: ServiceAccount +apiVersion: v1 +metadata: + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.tls.certs.selfSigner.svcAccountAnnotations }} + annotations: + {{- with .Values.tls.certs.selfSigner.svcAccountAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount-certSelfSigner.yaml new file mode 100644 index 000000000..3ce2d63e9 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount-certSelfSigner.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} + {{ template "cockroachdb.tls.certs.selfSigner.validation" . }} +kind: ServiceAccount +apiVersion: v1 +metadata: + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "1" + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + {{- with .Values.tls.certs.selfSigner.svcAccountAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount.yaml new file mode 100644 index 000000000..3af9be9aa --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/serviceaccount.yaml @@ -0,0 +1,21 @@ +{{- if .Values.statefulset.serviceAccount.create }} +kind: ServiceAccount +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.serviceAccount.name" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.statefulset.serviceAccount.annotations }} + annotations: + {{- with .Values.statefulset.serviceAccount.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/statefulset.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/statefulset.yaml new file mode 100644 index 000000000..a627c3516 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/statefulset.yaml @@ -0,0 +1,402 @@ +kind: StatefulSet +apiVersion: {{ template "cockroachdb.statefulset.apiVersion" . }} +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + serviceName: {{ template "cockroachdb.fullname" . }} + replicas: {{ .Values.statefulset.replicas | int64 }} + updateStrategy: {{- toYaml .Values.statefulset.updateStrategy | nindent 4 }} + podManagementPolicy: {{ .Values.statefulset.podManagementPolicy | quote }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.statefulset.annotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if or .Values.image.credentials (and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager)) }} + imagePullSecrets: + {{- if .Values.image.credentials }} + - name: {{ template "cockroachdb.fullname" . }}.db.registry + {{- end }} + {{- if and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager) }} + - name: {{ template "cockroachdb.fullname" . }}.self-signed-certs.registry + {{- end }} + {{- end }} + serviceAccountName: {{ template "cockroachdb.serviceAccount.name" . }} + {{- if .Values.tls.enabled }} + initContainers: + - name: copy-certs + image: {{ .Values.tls.copyCerts.image | quote }} + imagePullPolicy: {{ .Values.tls.selfSigner.image.pullPolicy | quote }} + command: + - /bin/sh + - -c + - "cp -f /certs/* /cockroach-certs/; chmod 0400 /cockroach-certs/*.key" + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.statefulset.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + {{- end }} + volumeMounts: + - name: certs + mountPath: /cockroach-certs/ + - name: certs-secret + mountPath: /certs/ + {{- with .Values.tls.copyCerts.resources }} + resources: {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if or .Values.statefulset.nodeAffinity .Values.statefulset.podAffinity .Values.statefulset.podAntiAffinity }} + affinity: + {{- with .Values.statefulset.nodeAffinity }} + nodeAffinity: {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.statefulset.podAffinity }} + podAffinity: {{- toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.statefulset.podAntiAffinity }} + podAntiAffinity: + {{- if .Values.statefulset.podAntiAffinity.type }} + {{- if eq .Values.statefulset.podAntiAffinity.type "hard" }} + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: {{ .Values.statefulset.podAntiAffinity.topologyKey }} + labelSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 18 }} + {{- end }} + {{- else if eq .Values.statefulset.podAntiAffinity.type "soft" }} + preferredDuringSchedulingIgnoredDuringExecution: + - weight: {{ .Values.statefulset.podAntiAffinity.weight | int64 }} + podAffinityTerm: + topologyKey: {{ .Values.statefulset.podAntiAffinity.topologyKey }} + labelSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 20 }} + {{- end }} + {{- end }} + {{- else }} + {{- toYaml .Values.statefulset.podAntiAffinity | nindent 10 }} + {{- end }} + {{- end }} + {{- end }} + {{- if semverCompare ">=1.16-0" .Capabilities.KubeVersion.Version }} + topologySpreadConstraints: + - labelSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.statefulset.topologySpreadConstraints }} + maxSkew: {{ .maxSkew }} + topologyKey: {{ .topologyKey }} + whenUnsatisfiable: {{ .whenUnsatisfiable }} + {{- end }} + {{- end }} + {{- with .Values.statefulset.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.statefulset.priorityClassName }} + priorityClassName: {{ .Values.statefulset.priorityClassName }} + {{- end }} + {{- with .Values.statefulset.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + # No pre-stop hook is required, a SIGTERM plus some time is all that's + # needed for graceful shutdown of a node. + terminationGracePeriodSeconds: 300 + containers: + - name: db + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + args: + - shell + - -ecx + # The use of qualified `hostname -f` is crucial: + # Other nodes aren't able to look up the unqualified hostname. + # + # `--join` CLI flag is hardcoded to exactly 3 Pods, because: + # 1. Having `--join` value depending on `statefulset.replicas` + # will trigger undesired restart of existing Pods when + # StatefulSet is scaled up/down. We want to scale without + # restarting existing Pods. + # 2. At least one Pod in `--join` is enough to successfully + # join CockroachDB cluster and gossip with all other existing + # Pods, even if there are 3 or more Pods. + # 3. It's harmless for `--join` to have 3 Pods even for 1-Pod + # clusters, while it gives us opportunity to scale up even if + # some Pods of existing cluster are down (for whatever reason). + # See details explained here: + # https://github.com/helm/charts/pull/18993#issuecomment-558795102 + - >- + exec /cockroach/cockroach + {{- if index .Values.conf `single-node` }} + start-single-node + {{- else }} + start --join= + {{- if .Values.conf.join }} + {{- join `,` .Values.conf.join -}} + {{- else }} + {{- range $i, $_ := until 3 -}} + {{- if gt $i 0 -}},{{- end -}} + ${STATEFULSET_NAME}-{{ $i }}.${STATEFULSET_FQDN}:{{ $.Values.service.ports.grpc.internal.port | int64 -}} + {{- end -}} + {{- end }} + {{- with index .Values.conf `cluster-name` }} + --cluster-name={{ . }} + {{- if index $.Values.conf `disable-cluster-name-verification` }} + --disable-cluster-name-verification + {{- end }} + {{- end }} + {{- end }} + --advertise-host=$(hostname).${STATEFULSET_FQDN} + {{- if .Values.tls.enabled }} + --certs-dir=/cockroach/cockroach-certs/ + {{- else }} + --insecure + {{- end }} + {{- with .Values.conf.attrs }} + --attrs={{ join `:` . }} + {{- end }} + --http-port={{ index .Values.conf `http-port` | int64 }} + --port={{ .Values.conf.port | int64 }} + --cache={{ .Values.conf.cache }} + {{- with index .Values.conf `max-disk-temp-storage` }} + --max-disk-temp-storage={{ . }} + {{- end }} + {{- with index .Values.conf `max-offset` }} + --max-offset={{ . }} + {{- end }} + --max-sql-memory={{ index .Values.conf `max-sql-memory` }} + {{- with .Values.conf.locality }} + --locality={{ . }} + {{- end }} + {{- with index .Values.conf `sql-audit-dir` }} + --sql-audit-dir={{ . }} + {{- end }} + {{- if .Values.conf.store.enabled }} + --store={{ template "cockroachdb.conf.store" . }} + {{- end }} + {{- if .Values.conf.log.enabled }} + --log-config-file=/cockroach/log-config/log-config.yaml + {{- else }} + --logtostderr={{ .Values.conf.logtostderr }} + {{- end }} + {{- range .Values.statefulset.args }} + {{ . }} + {{- end }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + - name: STATEFULSET_FQDN + value: {{ template "cockroachdb.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} + - name: COCKROACH_CHANNEL + value: kubernetes-helm + {{- with .Values.statefulset.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: grpc + containerPort: {{ .Values.conf.port | int64 }} + protocol: TCP + - name: http + containerPort: {{ index .Values.conf `http-port` | int64 }} + protocol: TCP + volumeMounts: + - name: datadir + mountPath: /cockroach/{{ .Values.conf.path }}/ + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /cockroach/cockroach-certs/ + {{- if .Values.tls.certs.provided }} + - name: certs-secret + mountPath: /cockroach/certs/ + {{- end }} + {{- end }} + {{- range .Values.statefulset.secretMounts }} + - name: {{ printf "secret-%s" . | quote }} + mountPath: {{ printf "/etc/cockroach/secrets/%s" . | quote }} + readOnly: true + {{- end }} + {{- if .Values.conf.log.enabled }} + - name: log-config + mountPath: /cockroach/log-config + readOnly: true + {{- end }} + livenessProbe: + {{- if .Values.statefulset.customLivenessProbe }} + {{ toYaml .Values.statefulset.customLivenessProbe | nindent 12 }} + {{- else }} + httpGet: + path: /health + port: http + {{- if .Values.tls.enabled }} + scheme: HTTPS + {{- end }} + initialDelaySeconds: 30 + periodSeconds: 5 + {{- end }} + readinessProbe: + {{- if .Values.statefulset.customReadinessProbe }} + {{ toYaml .Values.statefulset.customReadinessProbe | nindent 12 }} + {{- else }} + httpGet: + path: /health?ready=1 + port: http + {{- if .Values.tls.enabled }} + scheme: HTTPS + {{- end }} + initialDelaySeconds: 10 + periodSeconds: 5 + failureThreshold: 2 + {{- end }} + {{- if eq (include "cockroachdb.securityContext.versionValidation" .) "true" }} + {{- if .Values.statefulset.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + {{- end }} + {{- end }} + {{- with .Values.statefulset.resources }} + resources: {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: datadir + {{- if .Values.storage.persistentVolume.enabled }} + persistentVolumeClaim: + claimName: datadir + {{- else if .Values.storage.hostPath }} + hostPath: + path: {{ .Values.storage.hostPath | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} + - name: certs-secret + {{- if or .Values.tls.certs.tlsSecret .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} + projected: + sources: + - secret: + {{- if .Values.tls.certs.selfSigner.enabled }} + name: {{ template "cockroachdb.fullname" . }}-node-secret + {{ else }} + name: {{ .Values.tls.certs.nodeSecret }} + {{ end -}} + items: + - key: ca.crt + path: ca.crt + mode: 256 + - key: tls.crt + path: node.crt + mode: 256 + - key: tls.key + path: node.key + mode: 256 + {{- else }} + secret: + secretName: {{ .Values.tls.certs.nodeSecret }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- end }} + {{- range .Values.statefulset.secretMounts }} + - name: {{ printf "secret-%s" . | quote }} + secret: + secretName: {{ . | quote }} + {{- end }} + {{- if .Values.conf.log.enabled }} + - name: log-config + secret: + secretName: {{ template "cockroachdb.fullname" . }}-log-config + {{- end }} + {{- if eq (include "cockroachdb.securityContext.versionValidation" .) "true" }} + {{- if and .Values.securityContext.enabled }} + securityContext: + seccompProfile: + type: "RuntimeDefault" + fsGroup: 1000 + runAsGroup: 1000 + runAsUser: 1000 + runAsNonRoot: true + {{- end }} + {{- end }} +{{- if .Values.storage.persistentVolume.enabled }} + volumeClaimTemplates: + - metadata: + name: datadir + labels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.storage.persistentVolume.labels }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.storage.persistentVolume.annotations }} + annotations: {{- toYaml . | nindent 10 }} + {{- end }} + spec: + accessModes: ["ReadWriteOnce"] + {{- if .Values.storage.persistentVolume.storageClass }} + {{- if (eq "-" .Values.storage.persistentVolume.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.storage.persistentVolume.storageClass | quote}} + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.storage.persistentVolume.size | quote }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/templates/tests/client.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/templates/tests/client.yaml new file mode 100644 index 000000000..8656b8ed6 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/templates/tests/client.yaml @@ -0,0 +1,65 @@ +kind: Pod +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}-test + namespace: {{ .Release.Namespace | quote }} +{{- if .Values.networkPolicy.enabled }} + labels: + {{ template "cockroachdb.fullname" . }}-client: "true" +{{- end }} + annotations: + helm.sh/hook: test-success +spec: + restartPolicy: Never +{{- if .Values.image.credentials }} + imagePullSecrets: + - name: {{ template "cockroachdb.fullname" . }}.db.registry +{{- end }} + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager }} + volumes: + - name: client-certs + {{- if or .Values.tls.certs.tlsSecret .Values.tls.certs.certManager }} + projected: + sources: + - secret: + name: {{ .Values.tls.certs.clientRootSecret }} + items: + - key: ca.crt + path: ca.crt + mode: 0400 + - key: tls.crt + path: client.root.crt + mode: 0400 + - key: tls.key + path: client.root.key + mode: 0400 + {{- else }} + secret: + secretName: {{ .Values.tls.certs.clientRootSecret }} + defaultMode: 0400 + {{- end }} + {{- end }} + containers: + - name: client-test + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager }} + volumeMounts: + - name: client-certs + mountPath: /cockroach-certs + {{- end }} + command: + - /cockroach/cockroach + - sql + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager }} + - --certs-dir + - /cockroach-certs + {{- else }} + - --insecure + {{- end}} + - --host + - {{ template "cockroachdb.fullname" . }}-public.{{ .Release.Namespace }} + - --port + - {{ .Values.service.ports.grpc.external.port | quote }} + - -e + - SHOW DATABASES; diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/values.schema.json b/charts/cockroach-labs/cockroachdb/14.0.1/values.schema.json new file mode 100644 index 000000000..b23c47974 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/values.schema.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "tls": { + "type": "object", + "properties": { + "certs": { + "type": "object", + "properties": { + "selfSigner": { + "type": "object", + "required": ["enabled", "caProvided"], + "properties": { + "enabled": { + "type": "boolean" + }, + "caProvided": { + "type": "boolean" + } + }, + "if": { + "properties": { + "enabled": { + "const": true + } + } + }, + "then": { + "if": { + "properties": { + "caProvided": { + "const": false + } + } + }, + "then": { + "properties": { + "caCertDuration" : { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "caCertExpiryWindow": { + "type": "string", + "pattern": "^[0-9]*h$" + } + } + }, + "properties": { + "clientCertDuration": { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "clientCertExpiryWindow": { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "nodeCertDuration": { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "nodeCertExpiryWindow": { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "rotateCerts": { + "type": "boolean" + } + } + } + } + } + }, + "selfSigner": { + "type": "object", + "properties": { + "image": { + "type": "object", + "required": ["repository", "tag", "pullPolicy"], + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + }, + "pullPolicy": { + "type": "string", + "pattern": "^(Always|Never|IfNotPresent)$" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.1/values.yaml b/charts/cockroach-labs/cockroachdb/14.0.1/values.yaml new file mode 100644 index 000000000..40a4153c6 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.1/values.yaml @@ -0,0 +1,590 @@ +# Generated file, DO NOT EDIT. Source: build/templates/values.yaml +# Overrides the chart name against the label "app.kubernetes.io/name: " placed on every resource this chart creates. +nameOverride: "" + +# Override the resource names created by this chart which originally is generated using release and chart name. +fullnameOverride: "" + +image: + repository: cockroachdb/cockroach + tag: v24.2.1 + pullPolicy: IfNotPresent + credentials: {} + # registry: docker.io + # username: john_doe + # password: changeme + + +# Additional labels to apply to all Kubernetes resources created by this chart. +labels: {} + # app.kubernetes.io/part-of: my-app + + +# Cluster's default DNS domain. +# You should overwrite it if you're using a different one, +# otherwise CockroachDB nodes discovery won't work. +clusterDomain: cluster.local + + +conf: + # An ordered list of CockroachDB node attributes. + # Attributes are arbitrary strings specifying machine capabilities. + # Machine capabilities might include specialized hardware or number of cores + # (e.g. "gpu", "x16c"). + attrs: [] + # - x16c + # - gpu + + # Total size in bytes for caches, shared evenly if there are multiple + # storage devices. Size suffixes are supported (e.g. `1GB` and `1GiB`). + # A percentage of physical memory can also be specified (e.g. `.25`). + cache: 25% + + # Sets a name to verify the identity of a cluster. + # The value must match between all nodes specified via `conf.join`. + # This can be used as an additional verification when either the node or + # cluster, or both, have not yet been initialized and do not yet know their + # cluster ID. + # To introduce a cluster name into an already-initialized cluster, pair this + # option with `conf.disable-cluster-name-verification: yes`. + cluster-name: "" + + # Tell the server to ignore `conf.cluster-name` mismatches. + # This is meant for use when opting an existing cluster into starting to use + # cluster name verification, or when changing the cluster name. + # The cluster should be restarted once with `conf.cluster-name` and + # `conf.disable-cluster-name-verification: yes` combined, and once all nodes + # have been updated to know the new cluster name, the cluster can be restarted + # again with `conf.disable-cluster-name-verification: no`. + # This option has no effect if `conf.cluster-name` is not specified. + disable-cluster-name-verification: false + + # The addresses for connecting a CockroachDB nodes to an existing cluster. + # If you are deploying a second CockroachDB instance that should join a first + # one, use the below list to join to the existing instance. + # Each item in the array should be a FQDN (and port if needed) resolvable by + # new Pods. + join: [] + + # New logging configuration. + log: + enabled: false + # https://www.cockroachlabs.com/docs/v21.1/configure-logs + config: {} + # file-defaults: + # dir: /custom/dir/path/ + # fluent-defaults: + # format: json-fluent + # sinks: + # stderr: + # channels: [DEV] + + # Logs at or above this threshold to STDERR. Ignored when "log" is enabled + logtostderr: INFO + + # Maximum storage capacity available to store temporary disk-based data for + # SQL queries that exceed the memory budget (e.g. join, sorts, etc are + # sometimes able to spill intermediate results to disk). + # Accepts numbers interpreted as bytes, size suffixes (e.g. `32GB` and + # `32GiB`) or a percentage of disk size (e.g. `10%`). + # The location of the temporary files is within the first store dir. + # If expressed as a percentage, `max-disk-temp-storage` is interpreted + # relative to the size of the storage device on which the first store is + # placed. The temp space usage is never counted towards any store usage + # (although it does share the device with the first store) so, when + # configuring this, make sure that the size of this temp storage plus the size + # of the first store don't exceed the capacity of the storage device. + # If the first store is an in-memory one (i.e. `type=mem`), then this + # temporary "disk" data is also kept in-memory. + # A percentage value is interpreted as a percentage of the available internal + # memory. + # max-disk-temp-storage: 0GB + + # Maximum allowed clock offset for the cluster. If observed clock offsets + # exceed this limit, servers will crash to minimize the likelihood of + # reading inconsistent data. Increasing this value will increase the time + # to recovery of failures as well as the frequency of uncertainty-based + # read restarts. + # Note, that this value must be the same on all nodes in the cluster. + # In order to change it, all nodes in the cluster must be stopped + # simultaneously and restarted with the new value. + # max-offset: 500ms + + # Maximum memory capacity available to store temporary data for SQL clients, + # including prepared queries and intermediate data rows during query + # execution. Accepts numbers interpreted as bytes, size suffixes + # (e.g. `1GB` and `1GiB`) or a percentage of physical memory (e.g. `.25`). + max-sql-memory: 25% + + # An ordered, comma-separated list of key-value pairs that describe the + # topography of the machine. Topography might include country, datacenter + # or rack designations. Data is automatically replicated to maximize + # diversities of each tier. The order of tiers is used to determine + # the priority of the diversity, so the more inclusive localities like + # country should come before less inclusive localities like datacenter. + # The tiers and order must be the same on all nodes. Including more tiers + # is better than including fewer. For example: + # locality: country=us,region=us-west,datacenter=us-west-1b,rack=12 + # locality: country=ca,region=ca-east,datacenter=ca-east-2,rack=4 + # locality: planet=earth,province=manitoba,colo=secondary,power=3 + locality: "" + + # Run CockroachDB instances in standalone mode with replication disabled + # (replication factor = 1). + # Enabling this option makes the following values to be ignored: + # - `conf.cluster-name` + # - `conf.disable-cluster-name-verification` + # - `conf.join` + # + # WARNING: Enabling this option makes each deployed Pod as a STANDALONE + # CockroachDB instance, so the StatefulSet does NOT FORM A CLUSTER. + # Don't use this option for production deployments unless you clearly + # understand what you're doing. + # Usually, this option is intended to be used in conjunction with + # `statefulset.replicas: 1` for temporary one-time deployments (like + # running E2E tests, for example). + single-node: false + + # If non-empty, create a SQL audit log in the specified directory. + sql-audit-dir: "" + + # CockroachDB's port to listen to inter-communications and client connections. + port: 26257 + + # CockroachDB's port to listen to HTTP requests. + http-port: 8080 + + # CockroachDB's data mount path. + path: cockroach-data + + # CockroachDB's storage configuration https://www.cockroachlabs.com/docs/v21.1/cockroach-start.html#storage + # Uses --store flag + store: + enabled: false + # Should be empty or 'mem' + type: + # Required for type=mem. If type and size is empty - storage.persistentVolume.size is used + size: + # Arbitrary strings, separated by colons, specifying disk type or capability + attrs: + +statefulset: + replicas: 3 + updateStrategy: + type: RollingUpdate + podManagementPolicy: Parallel + budget: + maxUnavailable: 1 + + # List of additional command-line arguments you want to pass to the + # `cockroach start` command. + args: [] + # - --disable-cluster-name-verification + + # List of extra environment variables to pass into container + env: [] + # - name: COCKROACH_ENGINE_MAX_SYNC_DURATION + # value: "24h" + + # List of Secrets names in the same Namespace as the CockroachDB cluster, + # which shall be mounted into `/etc/cockroach/secrets/` for every cluster + # member. + secretMounts: [] + + # Additional labels to apply to this StatefulSet and all its Pods. + labels: + app.kubernetes.io/component: cockroachdb + + # Additional annotations to apply to the Pods of this StatefulSet. + annotations: {} + + # Affinity rules for scheduling Pods of this StatefulSet on Nodes. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + nodeAffinity: {} + # Inter-Pod Affinity rules for scheduling Pods of this StatefulSet. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity + podAffinity: {} + # Anti-affinity rules for scheduling Pods of this StatefulSet. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity + # You may either toggle options below for default anti-affinity rules, + # or specify the whole set of anti-affinity rules instead of them. + podAntiAffinity: + # The topologyKey to be used. + # Can be used to spread across different nodes, AZs, regions etc. + topologyKey: kubernetes.io/hostname + # Type of anti-affinity rules: either `soft`, `hard` or empty value (which + # disables anti-affinity rules). + type: soft + # Weight for `soft` anti-affinity rules. + # Does not apply for other anti-affinity types. + weight: 100 + + # Node selection constraints for scheduling Pods of this StatefulSet. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + nodeSelector: {} + + # PriorityClassName given to Pods of this StatefulSet + # https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass + priorityClassName: "" + + # Taints to be tolerated by Pods of this StatefulSet. + # https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + # https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + topologySpreadConstraints: + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + + # Uncomment the following resources definitions or pass them from + # command line to control the CPU and memory resources allocated + # by Pods of this StatefulSet. + resources: {} + # limits: + # cpu: 100m + # memory: 512Mi + # requests: + # cpu: 100m + # memory: 512Mi + + # Custom Liveness probe + # https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-http-request + customLivenessProbe: {} + # httpGet: + # path: /health + # port: http + # scheme: HTTPS + # initialDelaySeconds: 30 + # periodSeconds: 5 + + # Custom Rediness probe + # https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes + customReadinessProbe: {} + # httpGet: + # path: /health + # port: http + # scheme: HTTPS + # initialDelaySeconds: 30 + # periodSeconds: 5 + + securityContext: + enabled: true + + serviceAccount: + # Specifies whether this ServiceAccount should be created. + create: true + # The name of this ServiceAccount to use. + # If not set and `create` is `true`, then service account is auto-generated. + # If not set and `create` is `false`, then it uses default service account. + name: "" + # Additional serviceAccount annotations (e.g. for attaching AWS IAM roles to pods) + annotations: {} + +service: + ports: + # You can set a different external and internal gRPC ports and their name. + grpc: + external: + port: 26257 + name: grpc + # If the port number is different than `external.port`, then it will be + # named as `internal.name` in Service. + internal: + port: 26257 + # If using Istio set it to `cockroach`. + name: grpc-internal + http: + port: 8080 + name: http + + # This Service is meant to be used by clients of the database. + # It exposes a ClusterIP that will automatically load balance connections + # to the different database Pods. + public: + type: ClusterIP + # Additional labels to apply to this Service. + labels: + app.kubernetes.io/component: cockroachdb + # Additional annotations to apply to this Service. + annotations: {} + + # This service only exists to create DNS entries for each pod in + # the StatefulSet such that they can resolve each other's IP addresses. + # It does not create a load-balanced ClusterIP and should not be used directly + # by clients in most circumstances. + discovery: + # Additional labels to apply to this Service. + labels: + app.kubernetes.io/component: cockroachdb + # Additional annotations to apply to this Service. + annotations: {} + +# CockroachDB's ingress for web ui. +ingress: + enabled: false + labels: {} + annotations: {} + # kubernetes.io/ingress.class: nginx + # cert-manager.io/cluster-issuer: letsencrypt + paths: [/] + hosts: [] + # - cockroachlabs.com + tls: [] + # - hosts: [cockroachlabs.com] + # secretName: cockroachlabs-tls + +prometheus: + enabled: true + +securityContext: + enabled: true + +# CockroachDB's Prometheus operator ServiceMonitor support +serviceMonitor: + enabled: false + labels: {} + annotations: {} + interval: 10s + # scrapeTimeout: 10s + # Limits the ServiceMonitor to the current namespace if set to `true`. + namespaced: false + + # tlsConfig: TLS configuration to use when scraping the endpoint. + # Of type: https://github.com/coreos/prometheus-operator/blob/main/Documentation/api.md#tlsconfig + tlsConfig: {} + +# CockroachDB's data persistence. +# If neither `persistentVolume` nor `hostPath` is used, then data will be +# persisted in ad-hoc `emptyDir`. +storage: + # Absolute path on host to store CockroachDB's data. + # If not specified, then `emptyDir` will be used instead. + # If specified, but `persistentVolume.enabled` is `true`, then has no effect. + hostPath: "" + + # If `enabled` is `true` then a PersistentVolumeClaim will be created and + # used to store CockroachDB's data, otherwise `hostPath` is used. + persistentVolume: + enabled: true + + size: 100Gi + + # If defined, then `storageClassName: `. + # If set to "-", then `storageClassName: ""`, which disables dynamic + # provisioning. + # If undefined or empty (default), then no `storageClassName` spec is set, + # so the default provisioner will be chosen (gp2 on AWS, standard on + # GKE, AWS & OpenStack). + storageClass: "" + + # Additional labels to apply to the created PersistentVolumeClaims. + labels: {} + # Additional annotations to apply to the created PersistentVolumeClaims. + annotations: {} + + +# Kubernetes Job which initializes multi-node CockroachDB cluster. +# It's not created if `statefulset.replicas` is `1`. +init: + # Additional labels to apply to this Job and its Pod. + labels: + app.kubernetes.io/component: init + + # Additional annotations to apply to this Job. + jobAnnotations: {} + + # Additional annotations to apply to the Pod of this Job. + annotations: {} + + # Affinity rules for scheduling the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + affinity: {} + + # Node selection constraints for scheduling the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + nodeSelector: {} + + # Taints to be tolerated by the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + # The init Pod runs at cluster creation to initialize CockroachDB. It finishes + # quickly and doesn't continue to consume resources in the Kubernetes + # cluster. Normally, you should leave this section commented out, but if your + # Kubernetes cluster uses Resource Quotas and requires all pods to specify + # resource requests or limits, you can set those here. + resources: {} + # requests: + # cpu: "10m" + # memory: "128Mi" + # limits: + # cpu: "10m" + # memory: "128Mi" + + securityContext: + enabled: true + + provisioning: + enabled: false + # https://www.cockroachlabs.com/docs/stable/cluster-settings.html + clusterSettings: + # cluster.organization: "'FooCorp - Local Testing'" + # enterprise.license: "'xxxxx'" + users: [] + # - name: + # password: + # # https://www.cockroachlabs.com/docs/stable/create-user.html#parameters + # options: [LOGIN] + databases: [] + # - name: + # # https://www.cockroachlabs.com/docs/stable/create-database.html#parameters + # options: [encoding='utf-8'] + # owners: [] + # # https://www.cockroachlabs.com/docs/stable/grant.html#parameters + # owners_with_grant_option: [] + # # Backup schedules are not idemponent for now and will fail on next run + # # https://github.com/cockroachdb/cockroach/issues/57892 + # backup: + # into: s3:// + # # Enterprise-only option (revision_history) + # # https://www.cockroachlabs.com/docs/stable/create-schedule-for-backup.html#backup-options + # options: [revision_history] + # recurring: '@always' + # # Enterprise-only feature. Remove this value to use `FULL BACKUP ALWAYS` + # fullBackup: '@daily' + # schedule: + # # https://www.cockroachlabs.com/docs/stable/create-schedule-for-backup.html#schedule-options + # options: [first_run = 'now'] + + +# Whether to run securely using TLS certificates. +tls: + enabled: true + copyCerts: + image: busybox + certs: + # Bring your own certs scenario. If provided, tls.init section will be ignored. + provided: false + # Secret name for the client root cert. + clientRootSecret: cockroachdb-root + # Secret name for node cert. + nodeSecret: cockroachdb-node + # Secret name for CA cert + caSecret: cockroach-ca + # Enable if the secret is a dedicated TLS. + # TLS secrets are created by cert-mananger, for example. + tlsSecret: false + # Enable if the you want cockroach db to create its own certificates + selfSigner: + # If set, the cockroach db will generate its own certificates + enabled: true + # Run selfSigner as non-root + securityContext: + enabled: true + # If set, the user should provide the CA certificate to sign other certificates. + caProvided: false + # It holds the name of the secret with caCerts. If caProvided is set, this can not be empty. + caSecret: "" + # Minimum Certificate duration for all the certificates, all certs duration will be validated against this. + minimumCertDuration: 624h + # Duration of CA certificates in hour + caCertDuration: 43800h + # Expiry window of CA certificates means a window before actual expiry in which CA certs should be rotated. + caCertExpiryWindow: 648h + # Duration of Client certificates in hour + clientCertDuration: 672h + # Expiry window of client certificates means a window before actual expiry in which client certs should be rotated. + clientCertExpiryWindow: 48h + # Duration of node certificates in hour + nodeCertDuration: 8760h + # Expiry window of node certificates means a window before actual expiry in which node certs should be rotated. + nodeCertExpiryWindow: 168h + # If set, the cockroachdb cert selfSigner will rotate the certificates before expiry. + rotateCerts: true + # Wait time for each cockroachdb replica to become ready once it comes in running state. Only considered when rotateCerts is set to true + readinessWait: 30s + # Wait time for each cockroachdb replica to get to running state. Only considered when rotateCerts is set to true + podUpdateTimeout: 2m + # ServiceAccount annotations for selfSigner jobs (e.g. for attaching AWS IAM roles to pods) + svcAccountAnnotations: {} + + # Use cert-manager to issue certificates for mTLS. + certManager: false + # Specify an Issuer or a ClusterIssuer to use, when issuing + # node and client certificates. The values correspond to the + # issuerRef specified in the certificate. + certManagerIssuer: + group: cert-manager.io + kind: Issuer + name: cockroachdb + # Make it false when you are providing your own CA issuer + isSelfSignedIssuer: true + # Duration of CA certificates in hour + caCertDuration: 43800h + # Expiry window of CA certificates means a window before actual expiry in which CA certs should be rotated. + caCertExpiryWindow: 648h + # Duration of Client certificates in hours + clientCertDuration: 672h + # Expiry window of client certificates means a window before actual expiry in which client certs should be rotated. + clientCertExpiryWindow: 48h + # Duration of node certificates in hours + nodeCertDuration: 8760h + # Expiry window of node certificates means a window before actual expiry in which node certs should be rotated. + nodeCertExpiryWindow: 168h + + selfSigner: + # Additional annotations to apply to the Pod of this Job. + annotations: {} + + # Affinity rules for scheduling the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + affinity: {} + + # Node selection constraints for scheduling the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + nodeSelector: {} + + # Taints to be tolerated by the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + # Image Placeholder for the selfSigner utility. This will be changed once the CI workflows for the image is in place. + image: + repository: cockroachlabs-helm-charts/cockroach-self-signer-cert + tag: "1.5" + pullPolicy: IfNotPresent + credentials: {} + registry: gcr.io + # username: john_doe + # password: changeme + +networkPolicy: + enabled: false + + ingress: + # List of sources which should be able to access the CockroachDB Pods via + # gRPC port. Items in this list are combined using a logical OR operation. + # Rules for allowing inter-communication are applied automatically. + # If empty, then connections from any Pod is allowed. + grpc: [] + # - podSelector: + # matchLabels: + # app.kubernetes.io/name: my-app-django + # app.kubernetes.io/instance: my-app + + # List of sources which should be able to access the CockroachDB Pods via + # HTTP port. Items in this list are combined using a logical OR operation. + # If empty, then connections from any Pod is allowed. + http: [] + # - namespaceSelector: + # matchLabels: + # project: my-project + +# To put the admin interface behind Identity Aware Proxy (IAP) on Google Cloud Platform +# make sure to set ingress.paths: ['/*'] +iap: + enabled: false + # Create Google Cloud OAuth credentials and set client id and secret + # clientId: + # clientSecret: diff --git a/charts/codefresh/cf-runtime/6.3.58/.helmignore b/charts/codefresh/cf-runtime/6.3.58/.helmignore new file mode 100644 index 000000000..bc71d4240 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/.helmignore @@ -0,0 +1,3 @@ +tests/ +.ci/ +test-values/ \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/Chart.yaml b/charts/codefresh/cf-runtime/6.3.58/Chart.yaml new file mode 100644 index 000000000..51aa8d766 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/Chart.yaml @@ -0,0 +1,28 @@ +annotations: + artifacthub.io/changes: | + - kind: fixed + description: "Handling of image signing with certificate and private key password" + artifacthub.io/containsSecurityUpdates: "false" + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Codefresh + catalog.cattle.io/kube-version: '>=1.18-0' + catalog.cattle.io/release-name: cf-runtime +apiVersion: v2 +dependencies: +- name: cf-common + repository: file://./charts/cf-common + version: 0.16.0 +description: A Helm chart for Codefresh Runner +home: https://codefresh.io/ +icon: file://assets/icons/cf-runtime.png +keywords: +- codefresh +- runner +kubeVersion: '>=1.18-0' +maintainers: +- name: codefresh + url: https://codefresh-io.github.io/ +name: cf-runtime +sources: +- https://github.com/codefresh-io/venona +version: 6.3.58 diff --git a/charts/codefresh/cf-runtime/6.3.58/README.md b/charts/codefresh/cf-runtime/6.3.58/README.md new file mode 100644 index 000000000..9f633d405 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/README.md @@ -0,0 +1,1228 @@ +## Codefresh Runner + +![Version: 6.3.58](https://img.shields.io/badge/Version-6.3.58-informational?style=flat-square) + +Helm chart for deploying [Codefresh Runner](https://codefresh.io/docs/docs/installation/codefresh-runner/) to Kubernetes. + +## Table of Content + +- [Prerequisites](#prerequisites) +- [Get Chart Info](#get-chart-info) +- [Install Chart](#install-chart) +- [Chart Configuration](#chart-configuration) +- [Upgrade Chart](#upgrade-chart) + - [To 2.x](#to-2-x) + - [To 3.x](#to-3-x) + - [To 4.x](#to-4-x) + - [To 5.x](#to-5-x) + - [To 6.x](#to-6-x) +- [Architecture](#architecture) +- [Configuration](#configuration) + - [EBS backend volume configuration in AWS](#ebs-backend-volume-configuration) + - [Azure Disks backend volume configuration in AKS](#azure-disks-backend-volume-configuration) + - [GCE Disks backend volume configuration in GKE](#gce-disks-backend-volume-configuration-in-gke) + - [Custom volume mounts](#custom-volume-mounts) + - [Custom global environment variables](#custom-global-environment-variables) + - [Volume reuse policy](#volume-reuse-policy) + - [Volume cleaners](#volume-cleaners) + - [Rootless DinD](#rootless-dind) + - [ARM](#arm) + - [Openshift](#openshift) + - [On-premise](#on-premise) + +## Prerequisites + +- Kubernetes **1.19+** +- Helm **3.8.0+** + +⚠️⚠️⚠️ +> Since version 6.2.x chart is pushed **only** to OCI registry at `oci://quay.io/codefresh/cf-runtime` + +> Versions prior to 6.2.x are still available in ChartMuseum at `http://chartmuseum.codefresh.io/cf-runtime` + +## Get Chart Info + +```console +helm show all oci://quay.io/codefresh/cf-runtime +``` +See [Use OCI-based registries](https://helm.sh/docs/topics/registries/) + +## Install Chart + +**Important:** only helm3 is supported + +- Specify the following mandatory values + +`values.yaml` +```yaml +# -- Global parameters +# @default -- See below +global: + # -- User token in plain text (required if `global.codefreshTokenSecretKeyRef` is omitted!) + # Ref: https://g.codefresh.io/user/settings (see API Keys) + # Minimal API key scopes: Runner-Installation(read+write), Agent(read+write), Agents(read+write) + codefreshToken: "" + # -- User token that references an existing secret containing API key (required if `global.codefreshToken` is omitted!) + codefreshTokenSecretKeyRef: {} + # E.g. + # codefreshTokenSecretKeyRef: + # name: my-codefresh-api-token + # key: codefresh-api-token + + # -- Account ID (required!) + # Can be obtained here https://g.codefresh.io/2.0/account-settings/account-information + accountId: "" + + # -- K8s context name (required!) + context: "" + # E.g. + # context: prod-ue1-runtime-1 + + # -- Agent Name (optional!) + # If omitted, the following format will be used '{{ .Values.global.context }}_{{ .Release.Namespace }}' + agentName: "" + # E.g. + # agentName: prod-ue1-runtime-1 + + # -- Runtime name (optional!) + # If omitted, the following format will be used '{{ .Values.global.context }}/{{ .Release.Namespace }}' + runtimeName: "" + # E.g. + # runtimeName: prod-ue1-runtime-1/namespace +``` + +- Install chart + +```console +helm upgrade --install cf-runtime oci://quay.io/codefresh/cf-runtime -f values.yaml --create-namespace --namespace codefresh +``` + +## Chart Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). + +## Upgrade Chart + +### To 2.x + +This major release renames and deprecated several values in the chart. Most of the workload templates have been refactored. + +Affected values: +- `dockerRegistry` is deprecated. Replaced with `global.imageRegistry` +- `re` is renamed to `runtime` +- `storage.localVolumeMonitor` is replaced with `volumeProvisioner.dind-lv-monitor` +- `volumeProvisioner.volume-cleanup` is replaced with `volumeProvisioner.dind-volume-cleanup` +- `image` values structure has been updated. Split to `image.registry` `image.repository` `image.tag` +- pod's `annotations` is renamed to `podAnnotations` + +### To 3.x + +⚠️⚠️⚠️ +### READ this before the upgrade! + +This major release adds [runtime-environment](https://codefresh.io/docs/docs/installation/codefresh-runner/#runtime-environment-specification) spec into chart templates. +That means it is possible to set parametes for `dind` and `engine` pods via [values.yaml](./values.yaml). + +**If you had any overrides (i.e. tolerations/nodeSelector/environment variables/etc) added in runtime spec via [codefresh CLI](https://codefresh-io.github.io/cli/) (for example, you did use [get](https://codefresh-io.github.io/cli/runtime-environments/get-runtime-environments/) and [patch](https://codefresh-io.github.io/cli/runtime-environments/apply-runtime-environments/) commands to modify the runtime-environment), you MUST add these into chart's [values.yaml](./values.yaml) for `.Values.runtime.dind` or(and) .`Values.runtime.engine`** + +**For backward compatibility, you can disable updating runtime-environment spec via** `.Values.runtime.patch.enabled=false` + +Affected values: +- added **mandatory** `global.codefreshToken`/`global.codefreshTokenSecretKeyRef` **You must specify it before the upgrade!** +- `runtime.engine` is added +- `runtime.dind` is added +- `global.existingAgentToken` is replaced with `global.agentTokenSecretKeyRef` +- `global.existingDindCertsSecret` is replaced with `global.dindCertsSecretRef` + +### To 4.x + +This major release adds **agentless inCluster** runtime mode (relevant only for [Codefresh On-Premises](#on-premise) users) + +Affected values: +- `runtime.agent` / `runtime.inCluster` / `runtime.accounts` / `runtime.description` are added + +### To 5.x + +This major release converts `.runtime.dind.pvcs` from **list** to **dict** + +> 4.x chart's values example: +```yaml +runtime: + dind: + pvcs: + - name: dind + storageClassName: my-storage-class-name + volumeSize: 32Gi + reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName' + reuseVolumeSortOrder: pipeline_id +``` + +> 5.x chart's values example: +```yaml +runtime: + dind: + pvcs: + dind: + name: dind + storageClassName: my-storage-class-name + volumeSize: 32Gi + reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName' + reuseVolumeSortOrder: pipeline_id +``` + +Affected values: +- `.runtime.dind.pvcs` converted from **list** to **dict** + +### To 6.x + +⚠️⚠️⚠️ +### READ this before the upgrade! + +This major release deprecates previously required `codefresh runner init --generate-helm-values-file`. + +Affected values: +- **Replaced** `.monitor.clusterId` with `.global.context` as **mandatory** value! +- **Deprecated** `.global.agentToken` / `.global.agentTokenSecretKeyRef` +- **Removed** `.global.agentId` +- **Removed** `.global.keys` / `.global.dindCertsSecretRef` +- **Removed** `.global.existingAgentToken` / `existingDindCertsSecret` +- **Removed** `.monitor.clusterId` / `.monitor.token` / `.monitor.existingMonitorToken` + +#### Migrate the Helm chart from version 5.x to 6.x + +Given this is the legacy `generated_values.yaml` values: + +> legacy `generated_values.yaml` +```yaml +{ + "appProxy": { + "enabled": false, + }, + "monitor": { + "enabled": false, + "clusterId": "my-cluster-name", + "token": "1234567890" + }, + "global": { + "namespace": "namespace", + "codefreshHost": "https://g.codefresh.io", + "agentToken": "0987654321", + "agentId": "agent-id-here", + "agentName": "my-cluster-name_my-namespace", + "accountId": "my-account-id", + "runtimeName": "my-cluster-name/my-namespace", + "codefreshToken": "1234567890", + "keys": { + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "csr": "-----BEGIN CERTIFICATE REQUEST-----...", + "ca": "-----BEGIN CERTIFICATE-----...", + "serverCert": "-----BEGIN CERTIFICATE-----..." + } + } +} +``` + +Update `values.yaml` for new chart version: + +> For existing installation for backward compatibility `.Values.global.agentToken/agentTokenSecretKeyRef` **must be provided!** For installation from scratch this value is no longer required. + +> updated `values.yaml` +```yaml +global: + codefreshToken: "1234567890" + accountId: "my-account-id" + context: "my-cluster-name" + agentToken: "0987654321" # MANDATORY when migrating from < 6.x chart version ! + agentName: "my-cluster-name_my-namespace" # optional + runtimeName: "my-cluster-name/my-namespace" # optional +``` + +> **Note!** Though it's still possible to update runtime-environment via [get](https://codefresh-io.github.io/cli/runtime-environments/get-runtime-environments/) and [patch](https://codefresh-io.github.io/cli/runtime-environments/apply-runtime-environments/) commands, it's recommended to enable sidecar container to pull runtime spec from Codefresh API to detect any drift in configuration. + +```yaml +runner: + # -- Sidecar container + # Reconciles runtime spec from Codefresh API for drift detection + sidecar: + enabled: true +``` + +## Architecture + +[Codefresh Runner architecture](https://codefresh.io/docs/docs/installation/codefresh-runner/#codefresh-runner-architecture) + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). + +### EBS backend volume configuration + +`dind-volume-provisioner` should have permissions to create/attach/detach/delete/get EBS volumes + +Minimal IAM policy for `dind-volume-provisioner` + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AttachVolume", + "ec2:CreateSnapshot", + "ec2:CreateTags", + "ec2:CreateVolume", + "ec2:DeleteSnapshot", + "ec2:DeleteTags", + "ec2:DeleteVolume", + "ec2:DescribeInstances", + "ec2:DescribeSnapshots", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DetachVolume" + ], + "Resource": "*" + } + ] +} +``` + +There are three options: + +1. Run `dind-volume-provisioner` pod on the node/node-group with IAM role + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: ebs-csi + + ebs: + availabilityZone: "us-east-1a" + +volumeProvisioner: + # -- Set node selector + nodeSelector: {} + # -- Set tolerations + tolerations: [] +``` + +2. Pass static credentials in `.Values.storage.ebs.accessKeyId/accessKeyIdSecretKeyRef` and `.Values.storage.ebs.secretAccessKey/secretAccessKeySecretKeyRef` + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: ebs-csi + + ebs: + availabilityZone: "us-east-1a" + + # -- Set AWS_ACCESS_KEY_ID for volume-provisioner (optional) + accessKeyId: "" + # -- Existing secret containing AWS_ACCESS_KEY_ID. + accessKeyIdSecretKeyRef: {} + # E.g. + # accessKeyIdSecretKeyRef: + # name: + # key: + + # -- Set AWS_SECRET_ACCESS_KEY for volume-provisioner (optional) + secretAccessKey: "" + # -- Existing secret containing AWS_SECRET_ACCESS_KEY + secretAccessKeySecretKeyRef: {} + # E.g. + # secretAccessKeySecretKeyRef: + # name: + # key: +``` + +3. Assign IAM role to `dind-volume-provisioner` service account + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: ebs-csi + + ebs: + availabilityZone: "us-east-1a" + +volumeProvisioner: + # -- Service Account parameters + serviceAccount: + # -- Create service account + create: true + # -- Additional service account annotations + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam:::role/" +``` + +### Custom volume mounts + +You can add your own volumes and volume mounts in the runtime environment, so that all pipeline steps will have access to the same set of external files. + +```yaml +runtime: + dind: + userVolumes: + regctl-docker-registry: + name: regctl-docker-registry + secret: + items: + - key: .dockerconfigjson + path: config.json + secretName: regctl-docker-registry + optional: true + userVolumeMounts: + regctl-docker-registry: + name: regctl-docker-registry + mountPath: /home/appuser/.docker/ + readOnly: true + +``` + +### Azure Disks backend volume configuration + +`dind-volume-provisioner` should have permissions to create/delete/get Azure Disks + +Role definition for `dind-volume-provisioner` + +`dind-volume-provisioner-role.json` +```json +{ + "Name": "CodefreshDindVolumeProvisioner", + "Description": "Perform create/delete/get disks", + "IsCustom": true, + "Actions": [ + "Microsoft.Compute/disks/read", + "Microsoft.Compute/disks/write", + "Microsoft.Compute/disks/delete" + + ], + "AssignableScopes": ["/subscriptions/"] +} +``` + +When creating an AKS cluster in Azure there is the option to use a [managed identity](https://learn.microsoft.com/en-us/azure/aks/use-managed-identity) that is assigned to the kubelet. This identity is assigned to the underlying node pool in the AKS cluster and can then be used by the dind-volume-provisioner. + +```console +export ROLE_DEFINITIN_FILE=dind-volume-provisioner-role.json +export SUBSCRIPTION_ID=$(az account show --query "id" | xargs echo ) +export RESOURCE_GROUP= +export AKS_NAME= +export LOCATION=$(az aks show -g $RESOURCE_GROUP -n $AKS_NAME --query location | xargs echo) +export NODES_RESOURCE_GROUP=MC_${RESOURCE_GROUP}_${AKS_NAME}_${LOCATION} +export NODE_SERVICE_PRINCIPAL=$(az aks show -g $RESOURCE_GROUP -n $AKS_NAME --query identityProfile.kubeletidentity.objectId | xargs echo) + +az role definition create --role-definition @${ROLE_DEFINITIN_FILE} +az role assignment create --assignee $NODE_SERVICE_PRINCIPAL --scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$NODES_RESOURCE_GROUP --role CodefreshDindVolumeProvisioner +``` + +Deploy Helm chart with the following values: + +`values.yaml` +```yaml +volumeProvisioner: + podSecurityContext: + enabled: true + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + +storage: + backend: azuredisk + azuredisk: + availabilityZone: northeurope-1 # replace with your zone + resourceGroup: my-resource-group-name + + mountAzureJson: true + +runtime: + dind: + nodeSelector: + topology.kubernetes.io/zone: northeurope-1 +``` + +### GCE Disks backend volume configuration in GKE + +`dind-volume-provisioner` should have `ComputeEngine.StorageAdmin` permissions + +There are three options: + +1. Run `dind-volume-provisioner` pod on the node/node-group with IAM Service Account + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: gcedisk + + gcedisk: + # -- Set GCP volume backend type (`pd-ssd`/`pd-standard`) + volumeType: "pd-standard" + # -- Set GCP volume availability zone + availabilityZone: "us-central1-c" + +volumeProvisioner: + # -- Set node selector + nodeSelector: {} + # -- Set tolerations + tolerations: [] + +# -- Set runtime parameters +runtime: + # -- Parameters for DinD (docker-in-docker) pod + dind: + # -- Set node selector. + nodeSelector: + topology.kubernetes.io/zone: us-central1-c +``` + +2. Pass static credentials in `.Values.storage.gcedisk.serviceAccountJson` (inline) or `.Values.storage.gcedisk.serviceAccountJsonSecretKeyRef` (from your own secret) + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: gcedisk + + gcedisk: + # -- Set GCP volume backend type (`pd-ssd`/`pd-standard`) + volumeType: "`pd-standard" + # -- Set GCP volume availability zone + availabilityZone: "us-central1-c" + # -- Set Google SA JSON key for volume-provisioner (optional) + serviceAccountJson: | + { + "type": "service_account", + "project_id": "...", + "private_key_id": "...", + "private_key": "...", + "client_email": "...", + "client_id": "...", + "auth_uri": "...", + "token_uri": "...", + "auth_provider_x509_cert_url": "...", + "client_x509_cert_url": "..." + } + # -- Existing secret containing containing Google SA JSON key for volume-provisioner (optional) + serviceAccountJsonSecretKeyRef: {} + # E.g.: + # serviceAccountJsonSecretKeyRef: + # name: gce-service-account + # key: service-account.json + +# -- Set runtime parameters +runtime: + # -- Parameters for DinD (docker-in-docker) pod + dind: + # -- Set node selector. + nodeSelector: + topology.kubernetes.io/zone: us-central1-c +``` + +3. Assign IAM role to `dind-volume-provisioner` service account + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: gcedisk + + gcedisk: + # -- Set GCP volume backend type (`pd-ssd`/`pd-standard`) + volumeType: "`pd-standard" + # -- Set GCP volume availability zone + availabilityZone: "us-central1-c" + +volumeProvisioner: + # -- Service Account parameters + serviceAccount: + # -- Create service account + create: true + # -- Additional service account annotations + annotations: + iam.gke.io/gcp-service-account: @.iam.gserviceaccount.com + +# -- Set runtime parameters +runtime: + # -- Parameters for DinD (docker-in-docker) pod + dind: + # -- Set node selector. + nodeSelector: + topology.kubernetes.io/zone: us-central1-c +``` + +### Custom global environment variables + +You can add your own environment variables to the runtime environment. All pipeline steps have access to the global variables. + +```yaml +runtime: + engine: + userEnvVars: + - name: GITHUB_TOKEN + valueFrom: + secretKeyRef: + name: github-token + key: token +``` + +### Volume reuse policy + +Volume reuse behavior depends on the configuration for `reuseVolumeSelector` in the runtime environment spec. + +```yaml +runtime: + dind: + pvcs: + - name: dind + ... + reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName' + reuseVolumeSortOrder: pipeline_id +``` + +The following options are available: +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName'` - PV can be used by ANY pipeline in the specified account (default). +Benefit: Fewer PVs, resulting in lower costs. Since any PV can be used by any pipeline, the cluster needs to maintain/reserve fewer PVs in its PV pool for Codefresh. +Downside: Since the PV can be used by any pipeline, the PVs could have assets and info from different pipelines, reducing the probability of cache. + +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName,project_id'` - PV can be used by ALL pipelines in your account, assigned to the same project. + +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName,pipeline_id'` - PV can be used only by a single pipeline. +Benefit: More probability of cache without “spam” from other pipelines. +Downside: More PVs to maintain and therefore higher costs. + +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName,pipeline_id,io.codefresh.branch_name'` - PV can be used only by single pipeline AND single branch. + +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName,pipeline_id,trigger'` - PV can be used only by single pipeline AND single trigger. + +### Volume cleaners + +Codefresh pipelines require disk space for: + * [Pipeline Shared Volume](https://codefresh.io/docs/docs/pipelines/introduction-to-codefresh-pipelines/#sharing-the-workspace-between-build-steps) (`/codefresh/volume`, implemented as [docker volume](https://docs.docker.com/storage/volumes/)) + * Docker containers, both running and stopped + * Docker images and cached layers + +Codefresh offers two options to manage disk space and prevent out-of-space errors: +* Use runtime cleaners on Docker images and volumes +* [Set the minimum disk space per pipeline build volume](https://codefresh.io/docs/docs/pipelines/pipelines/#set-minimum-disk-space-for-a-pipeline-build) + +To improve performance by using Docker cache, Codefresh `volume-provisioner` can provision previously used disks with Docker images and pipeline volumes from previously run builds. + +### Types of runtime volume cleaners + +Docker images and volumes must be cleaned on a regular basis. + +* [IN-DIND cleaner](https://github.com/codefresh-io/dind/tree/master/cleaner): Deletes extra Docker containers, volumes, and images in **DIND pod**. +* [External volume cleaner](https://github.com/codefresh-io/dind-volume-cleanup): Deletes unused **external** PVs (EBS, GCE/Azure disks). +* [Local volume cleaner](https://github.com/codefresh-io/dind-volume-utils/blob/master/local-volumes/lv-cleaner.sh): Deletes **local** volumes if node disk space is close to the threshold. + +### IN-DIND cleaner + +**Purpose:** Removes unneeded *docker containers, images, volumes* inside Kubernetes volume mounted on the DIND pod + +**How it runs:** Inside each DIND pod as script + +**Triggered by:** SIGTERM and also during the run when disk usage > 90% (configurable) + +**Configured by:** Environment Variables which can be set in Runtime Environment spec + +**Configuration/Logic:** [README.md](https://github.com/codefresh-io/dind/tree/master/cleaner#readme) + +Override `.Values.runtime.dind.env` if necessary (the following are **defaults**): + +```yaml +runtime: + dind: + env: + CLEAN_PERIOD_SECONDS: '21600' # launch clean if last clean was more than CLEAN_PERIOD_SECONDS seconds ago + CLEAN_PERIOD_BUILDS: '5' # launch clean if last clean was more CLEAN_PERIOD_BUILDS builds since last build + IMAGE_RETAIN_PERIOD: '14400' # do not delete docker images if they have events since current_timestamp - IMAGE_RETAIN_PERIOD + VOLUMES_RETAIN_PERIOD: '14400' # do not delete docker volumes if they have events since current_timestamp - VOLUMES_RETAIN_PERIOD + DISK_USAGE_THRESHOLD: '0.8' # launch clean based on current disk usage DISK_USAGE_THRESHOLD + INODES_USAGE_THRESHOLD: '0.8' # launch clean based on current inodes usage INODES_USAGE_THRESHOLD +``` + +### External volumes cleaner + +**Purpose:** Removes unused *kubernetes volumes and related backend volumes* + +**How it runs:** Runs as `dind-volume-cleanup` CronJob. Installed in case the Runner uses non-local volumes `.Values.storage.backend != local` + +**Triggered by:** CronJob every 10min (configurable) + +**Configuration:** + +Set `codefresh.io/volume-retention` for dinds' PVCs: + +```yaml +runtime: + dind: + pvcs: + dind: + ... + annotations: + codefresh.io/volume-retention: 7d +``` + +Or override environment variables for `dind-volume-cleanup` cronjob: + +```yaml +volumeProvisioner: + dind-volume-cleanup: + env: + RETENTION_DAYS: 7 # clean volumes that were last used more than `RETENTION_DAYS` (default is 4) ago +``` + +### Local volumes cleaner + +**Purpose:** Deletes local volumes when node disk space is close to the threshold + +**How it runs:** Runs as `dind-lv-monitor` DaemonSet. Installed in case the Runner uses local volumes `.Values.storage.backend == local` + +**Triggered by:** Disk space usage or inode usage that exceeds thresholds (configurable) + +**Configuration:** + +Override environment variables for `dind-lv-monitor` daemonset: + +```yaml +volumeProvisioner: + dind-lv-monitor: + env: + KB_USAGE_THRESHOLD: 60 # default 80 (percentage) + INODE_USAGE_THRESHOLD: 60 # default 80 +``` + +### Rootless DinD + +DinD pod runs a `priviliged` container with **rootfull** docker. +To run the docker daemon as non-root user (**rootless** mode), change dind image tag: + +`values.yaml` +```yaml +runtime: + dind: + image: + tag: rootless +``` + +### ARM + +With the Codefresh Runner, you can run native ARM64v8 builds. + +> **Note!** +> You cannot run both amd64 and arm64 images within the same pipeline. As one pipeline can map only to one runtime, you can run either amd64 or arm64 within the same pipeline. + +Provide `nodeSelector` and(or) `tolerations` for dind pods: + +`values.yaml` +```yaml +runtime: + dind: + nodeSelector: + arch: arm64 + tolerations: + - key: arch + operator: Equal + value: arm64 + effect: NoSchedule +``` + +### Openshift + +To install Codefresh Runner on OpenShift use the following `values.yaml` example + +```yaml +runner: + podSecurityContext: + enabled: false + +volumeProvisioner: + podSecurityContext: + enabled: false + env: + PRIVILEGED_CONTAINER: true + dind-lv-monitor: + containerSecurityContext: + enabled: true + privileged: true + volumePermissions: + enabled: true + securityContext: + privileged: true + runAsUser: auto +``` + +Grant `privileged` SCC to `cf-runtime-runner` and `cf-runtime-volume-provisioner` service accounts. + +```console +oc adm policy add-scc-to-user privileged system:serviceaccount:codefresh:cf-runtime-runner + +oc adm policy add-scc-to-user privileged system:serviceaccount:codefresh:cf-runtime-volume-provisioner +``` + +### On-premise + +If you have [Codefresh On-Premises](https://artifacthub.io/packages/helm/codefresh-onprem/codefresh) deployed, you can install Codefresh Runner in **agentless** mode. + +**What is agentless mode?** + +Agent (aka venona) is Runner component which responsible for calling Codefresh API to run builds and create dind/engine pods and pvc objects. Agent can only be assigned to a single account, thus you can't share one runtime across multiple accounts. However, with **agentless** mode it's possible to register the runtime as **system**-type runtime so it's registered on the platform level and can be assigned/shared across multiple accounts. + +**What are the prerequisites?** +- You have a running [Codefresh On-Premises](https://artifacthub.io/packages/helm/codefresh-onprem/codefresh) control-plane environment +- You have a Codefresh API token with platform **Admin** permissions scope + +### How to deploy agentless runtime when it's on the SAME k8s cluster as On-Premises control-plane environment? + +- Enable cluster-level permissions for cf-api (On-Premises control-plane component) + +> `values.yaml` for [Codefresh On-Premises](https://artifacthub.io/packages/helm/codefresh-onprem/codefresh) Helm chart +```yaml +cfapi: + ... + # -- Enable ClusterRole/ClusterRoleBinding + rbac: + namespaced: false +``` + +- Set the following values for Runner Helm chart + +`.Values.global.codefreshHost=...` \ +`.Values.global.codefreshToken=...` \ +`.Values.global.runtimeName=system/...` \ +`.Values.runtime.agent=false` \ +`.Values.runtime.inCluster=true` + +> `values.yaml` for [Codefresh Runner](https://artifacthub.io/packages/helm/codefresh-runner/cf-runtime) helm chart +```yaml +global: + # -- URL of Codefresh On-Premises Platform + codefreshHost: "https://myonprem.somedomain.com" + # -- User token in plain text with Admin permission scope + codefreshToken: "" + # -- User token that references an existing secret containing API key. + codefreshTokenSecretKeyRef: {} + # E.g. + # codefreshTokenSecretKeyRef: + # name: my-codefresh-api-token + # key: codefresh-api-token + + # -- Distinguished runtime name + # (for On-Premise only; mandatory!) Must be prefixed with "system/..." + runtimeName: "system/prod-ue1-some-cluster-name" + +# -- Set runtime parameters +runtime: + # -- (for On-Premise only; mandatory!) Disable agent + agent: false + # -- (for On-Premise only; optional) Set inCluster runtime (default: `true`) + # `inCluster=true` flag is set when Runtime and On-Premises control-plane are run on the same cluster + # `inCluster=false` flag is set when Runtime and On-Premises control-plane are on different clusters + inCluster: true + # -- (for On-Premise only; optional) Assign accounts to runtime (list of account ids; default is empty) + # Accounts can be assigned to the runtime in Codefresh UI later so you can kepp it empty. + accounts: [] + # -- Set parent runtime to inherit. + runtimeExtends: [] +``` + +- Install the chart + +```console +helm upgrade --install cf-runtime oci://quay.io/codefresh/cf-runtime -f values.yaml --create-namespace --namespace cf-runtime +``` + +- Verify the runtime and run test pipeline + +Go to [https:///admin/runtime-environments/system](https:///admin/runtime-environments/system) to check the runtime. Assign it to the required account(s). Run test pipeline on it. + +### How to deploy agentless runtime when it's on the DIFFERENT k8s cluster than On-Premises control-plane environment? + +In this case, it's required to mount runtime cluster's `KUBECONFIG` into On-Premises `cf-api` deployment + +- Create the neccessary RBAC resources + +> `values.yaml` for [Codefresh Runner](https://artifacthub.io/packages/helm/codefresh-runner/cf-runtime) helm chart +```yaml +extraResources: +- apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: codefresh-role + namespace: '{{ .Release.Namespace }}' + rules: + - apiGroups: [""] + resources: ["pods", "persistentvolumeclaims", "persistentvolumes"] + verbs: ["list", "watch", "get", "create", "patch", "delete"] + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshots"] + verbs: ["list", "watch", "get", "create", "patch", "delete"] +- apiVersion: v1 + kind: ServiceAccount + metadata: + name: codefresh-runtime-user + namespace: '{{ .Release.Namespace }}' +- apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: codefresh-runtime-user + namespace: '{{ .Release.Namespace }}' + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: codefresh-role + subjects: + - kind: ServiceAccount + name: codefresh-runtime-user + namespace: '{{ .Release.Namespace }}' +- apiVersion: v1 + kind: Secret + metadata: + name: codefresh-runtime-user-token + namespace: '{{ .Release.Namespace }}' + annotations: + kubernetes.io/service-account.name: codefresh-runtime-user + type: kubernetes.io/service-account-token +``` + +- Set up the following environment variables to create a `KUBECONFIG` file + +```shell +NAMESPACE=cf-runtime +CLUSTER_NAME=prod-ue1-some-cluster-name +CURRENT_CONTEXT=$(kubectl config current-context) + +USER_TOKEN_VALUE=$(kubectl -n cf-runtime get secret/codefresh-runtime-user-token -o=go-template='{{.data.token}}' | base64 --decode) +CURRENT_CLUSTER=$(kubectl config view --raw -o=go-template='{{range .contexts}}{{if eq .name "'''${CURRENT_CONTEXT}'''"}}{{ index .context "cluster" }}{{end}}{{end}}') +CLUSTER_CA=$(kubectl config view --raw -o=go-template='{{range .clusters}}{{if eq .name "'''${CURRENT_CLUSTER}'''"}}"{{with index .cluster "certificate-authority-data" }}{{.}}{{end}}"{{ end }}{{ end }}') +CLUSTER_SERVER=$(kubectl config view --raw -o=go-template='{{range .clusters}}{{if eq .name "'''${CURRENT_CLUSTER}'''"}}{{ .cluster.server }}{{end}}{{ end }}') + +export -p USER_TOKEN_VALUE CURRENT_CONTEXT CURRENT_CLUSTER CLUSTER_CA CLUSTER_SERVER CLUSTER_NAME +``` + +- Create a kubeconfig file + +```console +cat << EOF > $CLUSTER_NAME-kubeconfig +apiVersion: v1 +kind: Config +current-context: ${CLUSTER_NAME} +contexts: +- name: ${CLUSTER_NAME} + context: + cluster: ${CLUSTER_NAME} + user: codefresh-runtime-user + namespace: ${NAMESPACE} +clusters: +- name: ${CLUSTER_NAME} + cluster: + certificate-authority-data: ${CLUSTER_CA} + server: ${CLUSTER_SERVER} +users: +- name: ${CLUSTER_NAME} + user: + token: ${USER_TOKEN_VALUE} +EOF +``` + +- **Switch context to On-Premises control-plane cluster**. Create k8s secret (via any tool like [ESO](https://external-secrets.io/v0.4.4/), `kubectl`, etc ) containing runtime cluster's `KUBECONFG` created in previous step. + +```shell +NAMESPACE=codefresh +kubectl create secret generic dind-runtime-clusters --from-file=$CLUSTER_NAME=$CLUSTER_NAME-kubeconfig -n $NAMESPACE +``` + +- Mount secret containing runtime cluster's `KUBECONFG` into cf-api in On-Premises control-plane cluster + +> `values.yaml` for [Codefresh On-Premises](https://artifacthub.io/packages/helm/codefresh-onprem/codefresh) helm chart +```yaml +cf-api: + ... + volumes: + dind-clusters: + enabled: true + type: secret + nameOverride: dind-runtime-clusters + optional: true +``` +> volumeMount `/etc/kubeconfig` is already configured in cf-api Helm chart template. No need to specify it. + +- Set the following values for Runner helm chart + +> `values.yaml` for [Codefresh Runner](https://artifacthub.io/packages/helm/codefresh-runner/cf-runtime) helm chart + +`.Values.global.codefreshHost=...` \ +`.Values.global.codefreshToken=...` \ +`.Values.global.runtimeName=system/...` \ +`.Values.runtime.agent=false` \ +`.Values.runtime.inCluster=false` + +**Important!** +`.Values.global.name` ("system/" prefix is ignored!) should match the cluster name (key in `dind-runtime-clusters` secret created previously) +```yaml +global: + # -- URL of Codefresh On-Premises Platform + codefreshHost: "https://myonprem.somedomain.com" + # -- User token in plain text with Admin permission scope + codefreshToken: "" + # -- User token that references an existing secret containing API key. + codefreshTokenSecretKeyRef: {} + # E.g. + # codefreshTokenSecretKeyRef: + # name: my-codefresh-api-token + # key: codefresh-api-token + + # -- Distinguished runtime name + # (for On-Premise only; mandatory!) Must be prefixed with "system/..." + name: "system/prod-ue1-some-cluster-name" + +# -- Set runtime parameters +runtime: + # -- (for On-Premise only; mandatory!) Disable agent + agent: false + # -- (for On-Premise only; optional) Set inCluster runtime (default: `true`) + # `inCluster=true` flag is set when Runtime and On-Premises control-plane are run on the same cluster + # `inCluster=false` flag is set when Runtime and On-Premises control-plane are on different clusters + inCluster: false + # -- (for On-Premise only; optional) Assign accounts to runtime (list of account ids; default is empty) + # Accounts can be assigned to the runtime in Codefresh UI later so you can kepp it empty. + accounts: [] + # -- (optional) Set parent runtime to inherit. + runtimeExtends: [] +``` + +- Install the chart + +```console +helm upgrade --install cf-runtime oci://quay.io/codefresh/cf-runtime -f values.yaml --create-namespace --namespace cf-runtime +``` + +- Verify the runtime and run test pipeline + +Go to [https:///admin/runtime-environments/system](https:///admin/runtime-environments/system) to see the runtime. Assign it to the required account(s). + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| oci://quay.io/codefresh/charts | cf-common | 0.16.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| appProxy.affinity | object | `{}` | Set affinity | +| appProxy.enabled | bool | `false` | Enable app-proxy | +| appProxy.env | object | `{}` | Add additional env vars | +| appProxy.image | object | `{"registry":"quay.io","repository":"codefresh/cf-app-proxy","tag":"0.0.47"}` | Set image | +| appProxy.ingress.annotations | object | `{}` | Set extra annotations for ingress object | +| appProxy.ingress.class | string | `""` | Set ingress class | +| appProxy.ingress.host | string | `""` | Set DNS hostname the ingress will use | +| appProxy.ingress.pathPrefix | string | `""` | Set path prefix for ingress (keep empty for default `/` path) | +| appProxy.ingress.tlsSecret | string | `""` | Set k8s tls secret for the ingress object | +| appProxy.nodeSelector | object | `{}` | Set node selector | +| appProxy.podAnnotations | object | `{}` | Set pod annotations | +| appProxy.podSecurityContext | object | `{}` | Set security context for the pod | +| appProxy.rbac | object | `{"create":true,"namespaced":true,"rules":[]}` | RBAC parameters | +| appProxy.rbac.create | bool | `true` | Create RBAC resources | +| appProxy.rbac.namespaced | bool | `true` | Use Role(true)/ClusterRole(true) | +| appProxy.rbac.rules | list | `[]` | Add custom rule to the role | +| appProxy.readinessProbe | object | See below | Readiness probe configuration | +| appProxy.replicasCount | int | `1` | Set number of pods | +| appProxy.resources | object | `{}` | Set requests and limits | +| appProxy.serviceAccount | object | `{"annotations":{},"create":true,"name":"","namespaced":true}` | Service Account parameters | +| appProxy.serviceAccount.annotations | object | `{}` | Additional service account annotations | +| appProxy.serviceAccount.create | bool | `true` | Create service account | +| appProxy.serviceAccount.name | string | `""` | Override service account name | +| appProxy.serviceAccount.namespaced | bool | `true` | Use Role(true)/ClusterRole(true) | +| appProxy.tolerations | list | `[]` | Set tolerations | +| appProxy.updateStrategy | object | `{"type":"RollingUpdate"}` | Upgrade strategy | +| dockerRegistry | string | `""` | | +| event-exporter | object | See below | Event exporter parameters | +| event-exporter.affinity | object | `{}` | Set affinity | +| event-exporter.enabled | bool | `false` | Enable event-exporter | +| event-exporter.env | object | `{}` | Add additional env vars | +| event-exporter.image | object | `{"registry":"docker.io","repository":"codefresh/k8s-event-exporter","tag":"latest"}` | Set image | +| event-exporter.nodeSelector | object | `{}` | Set node selector | +| event-exporter.podAnnotations | object | `{}` | Set pod annotations | +| event-exporter.podSecurityContext | object | See below | Set security context for the pod | +| event-exporter.rbac | object | `{"create":true,"rules":[]}` | RBAC parameters | +| event-exporter.rbac.create | bool | `true` | Create RBAC resources | +| event-exporter.rbac.rules | list | `[]` | Add custom rule to the role | +| event-exporter.replicasCount | int | `1` | Set number of pods | +| event-exporter.resources | object | `{}` | Set resources | +| event-exporter.serviceAccount | object | `{"annotations":{},"create":true,"name":""}` | Service Account parameters | +| event-exporter.serviceAccount.annotations | object | `{}` | Additional service account annotations | +| event-exporter.serviceAccount.create | bool | `true` | Create service account | +| event-exporter.serviceAccount.name | string | `""` | Override service account name | +| event-exporter.tolerations | list | `[]` | Set tolerations | +| event-exporter.updateStrategy | object | `{"type":"Recreate"}` | Upgrade strategy | +| extraResources | list | `[]` | Array of extra objects to deploy with the release | +| fullnameOverride | string | `""` | String to fully override cf-runtime.fullname template | +| global | object | See below | Global parameters | +| global.accountId | string | `""` | Account ID (required!) Can be obtained here https://g.codefresh.io/2.0/account-settings/account-information | +| global.agentName | string | `""` | Agent Name (optional!) If omitted, the following format will be used `{{ .Values.global.context }}_{{ .Release.Namespace }}` | +| global.agentToken | string | `""` | DEPRECATED Agent token in plain text. !!! MUST BE provided if migrating from < 6.x chart version | +| global.agentTokenSecretKeyRef | object | `{}` | DEPRECATED Agent token that references an existing secret containing API key. !!! MUST BE provided if migrating from < 6.x chart version | +| global.codefreshHost | string | `"https://g.codefresh.io"` | URL of Codefresh Platform (required!) | +| global.codefreshToken | string | `""` | User token in plain text (required if `global.codefreshTokenSecretKeyRef` is omitted!) Ref: https://g.codefresh.io/user/settings (see API Keys) Minimal API key scopes: Runner-Installation(read+write), Agent(read+write), Agents(read+write) | +| global.codefreshTokenSecretKeyRef | object | `{}` | User token that references an existing secret containing API key (required if `global.codefreshToken` is omitted!) | +| global.context | string | `""` | K8s context name (required!) | +| global.imagePullSecrets | list | `[]` | Global Docker registry secret names as array | +| global.imageRegistry | string | `""` | Global Docker image registry | +| global.runtimeName | string | `""` | Runtime name (optional!) If omitted, the following format will be used `{{ .Values.global.context }}/{{ .Release.Namespace }}` | +| monitor.affinity | object | `{}` | Set affinity | +| monitor.enabled | bool | `false` | Enable monitor Ref: https://codefresh.io/docs/docs/installation/codefresh-runner/#install-monitoring-component | +| monitor.env | object | `{}` | Add additional env vars | +| monitor.image | object | `{"registry":"quay.io","repository":"codefresh/cf-k8s-agent","tag":"1.3.17"}` | Set image | +| monitor.nodeSelector | object | `{}` | Set node selector | +| monitor.podAnnotations | object | `{}` | Set pod annotations | +| monitor.podSecurityContext | object | `{}` | | +| monitor.rbac | object | `{"create":true,"namespaced":true,"rules":[]}` | RBAC parameters | +| monitor.rbac.create | bool | `true` | Create RBAC resources | +| monitor.rbac.namespaced | bool | `true` | Use Role(true)/ClusterRole(true) | +| monitor.rbac.rules | list | `[]` | Add custom rule to the role | +| monitor.readinessProbe | object | See below | Readiness probe configuration | +| monitor.replicasCount | int | `1` | Set number of pods | +| monitor.resources | object | `{}` | Set resources | +| monitor.serviceAccount | object | `{"annotations":{},"create":true,"name":""}` | Service Account parameters | +| monitor.serviceAccount.annotations | object | `{}` | Additional service account annotations | +| monitor.serviceAccount.create | bool | `true` | Create service account | +| monitor.serviceAccount.name | string | `""` | Override service account name | +| monitor.tolerations | list | `[]` | Set tolerations | +| monitor.updateStrategy | object | `{"type":"RollingUpdate"}` | Upgrade strategy | +| nameOverride | string | `""` | String to partially override cf-runtime.fullname template (will maintain the release name) | +| podMonitor | object | See below | Add podMonitor (for engine pods) | +| podMonitor.main.enabled | bool | `false` | Enable pod monitor for engine pods | +| podMonitor.runner.enabled | bool | `false` | Enable pod monitor for runner pod | +| podMonitor.volume-provisioner.enabled | bool | `false` | Enable pod monitor for volumeProvisioner pod | +| re | object | `{}` | | +| runner | object | See below | Runner parameters | +| runner.affinity | object | `{}` | Set affinity | +| runner.enabled | bool | `true` | Enable the runner | +| runner.env | object | `{}` | Add additional env vars | +| runner.image | object | `{"registry":"quay.io","repository":"codefresh/venona","tag":"1.10.2"}` | Set image | +| runner.init | object | `{"image":{"registry":"quay.io","repository":"codefresh/cli","tag":"0.85.0-rootless"},"resources":{"limits":{"cpu":"1","memory":"512Mi"},"requests":{"cpu":"0.2","memory":"256Mi"}}}` | Init container | +| runner.nodeSelector | object | `{}` | Set node selector | +| runner.podAnnotations | object | `{}` | Set pod annotations | +| runner.podSecurityContext | object | See below | Set security context for the pod | +| runner.rbac | object | `{"create":true,"rules":[]}` | RBAC parameters | +| runner.rbac.create | bool | `true` | Create RBAC resources | +| runner.rbac.rules | list | `[]` | Add custom rule to the role | +| runner.readinessProbe | object | See below | Readiness probe configuration | +| runner.replicasCount | int | `1` | Set number of pods | +| runner.resources | object | `{}` | Set requests and limits | +| runner.serviceAccount | object | `{"annotations":{},"create":true,"name":""}` | Service Account parameters | +| runner.serviceAccount.annotations | object | `{}` | Additional service account annotations | +| runner.serviceAccount.create | bool | `true` | Create service account | +| runner.serviceAccount.name | string | `""` | Override service account name | +| runner.sidecar | object | `{"enabled":false,"env":{"RECONCILE_INTERVAL":300},"image":{"registry":"quay.io","repository":"codefresh/codefresh-shell","tag":"0.0.2"},"resources":{}}` | Sidecar container Reconciles runtime spec from Codefresh API for drift detection | +| runner.tolerations | list | `[]` | Set tolerations | +| runner.updateStrategy | object | `{"type":"RollingUpdate"}` | Upgrade strategy | +| runtime | object | See below | Set runtime parameters | +| runtime.accounts | list | `[]` | (for On-Premise only) Assign accounts to runtime (list of account ids) | +| runtime.agent | bool | `true` | (for On-Premise only) Enable agent | +| runtime.description | string | `""` | Runtime description | +| runtime.dind | object | `{"affinity":{},"env":{"DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE":true},"image":{"pullPolicy":"IfNotPresent","registry":"quay.io","repository":"codefresh/dind","tag":"26.1.4-1.28.7"},"nodeSelector":{},"podAnnotations":{},"podLabels":{},"pvcs":{"dind":{"annotations":{},"name":"dind","reuseVolumeSelector":"codefresh-app,io.codefresh.accountName","reuseVolumeSortOrder":"pipeline_id","storageClassName":"{{ include \"dind-volume-provisioner.storageClassName\" . }}","volumeSize":"16Gi"}},"resources":{"limits":{"cpu":"400m","memory":"800Mi"},"requests":null},"schedulerName":"","serviceAccount":"codefresh-engine","tolerations":[],"userAccess":true,"userVolumeMounts":{},"userVolumes":{}}` | Parameters for DinD (docker-in-docker) pod (aka "runtime" pod). | +| runtime.dind.affinity | object | `{}` | Set affinity | +| runtime.dind.env | object | `{"DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE":true}` | Set additional env vars. | +| runtime.dind.image | object | `{"pullPolicy":"IfNotPresent","registry":"quay.io","repository":"codefresh/dind","tag":"26.1.4-1.28.7"}` | Set dind image. | +| runtime.dind.nodeSelector | object | `{}` | Set node selector. | +| runtime.dind.podAnnotations | object | `{}` | Set pod annotations. | +| runtime.dind.podLabels | object | `{}` | Set pod labels. | +| runtime.dind.pvcs | object | `{"dind":{"annotations":{},"name":"dind","reuseVolumeSelector":"codefresh-app,io.codefresh.accountName","reuseVolumeSortOrder":"pipeline_id","storageClassName":"{{ include \"dind-volume-provisioner.storageClassName\" . }}","volumeSize":"16Gi"}}` | PV claim spec parametes. | +| runtime.dind.pvcs.dind | object | `{"annotations":{},"name":"dind","reuseVolumeSelector":"codefresh-app,io.codefresh.accountName","reuseVolumeSortOrder":"pipeline_id","storageClassName":"{{ include \"dind-volume-provisioner.storageClassName\" . }}","volumeSize":"16Gi"}` | Default dind PVC parameters | +| runtime.dind.pvcs.dind.annotations | object | `{}` | PV annotations. | +| runtime.dind.pvcs.dind.name | string | `"dind"` | PVC name prefix. Keep `dind` as default! Don't change! | +| runtime.dind.pvcs.dind.reuseVolumeSelector | string | `"codefresh-app,io.codefresh.accountName"` | PV reuse selector. Ref: https://codefresh.io/docs/docs/installation/codefresh-runner/#volume-reuse-policy | +| runtime.dind.pvcs.dind.storageClassName | string | `"{{ include \"dind-volume-provisioner.storageClassName\" . }}"` | PVC storage class name. Change ONLY if you need to use storage class NOT from Codefresh volume-provisioner | +| runtime.dind.pvcs.dind.volumeSize | string | `"16Gi"` | PVC size. | +| runtime.dind.resources | object | `{"limits":{"cpu":"400m","memory":"800Mi"},"requests":null}` | Set dind resources. | +| runtime.dind.schedulerName | string | `""` | Set scheduler name. | +| runtime.dind.serviceAccount | string | `"codefresh-engine"` | Set service account for pod. | +| runtime.dind.tolerations | list | `[]` | Set tolerations. | +| runtime.dind.userAccess | bool | `true` | Keep `true` as default! | +| runtime.dind.userVolumeMounts | object | `{}` | Add extra volume mounts | +| runtime.dind.userVolumes | object | `{}` | Add extra volumes | +| runtime.dindDaemon | object | See below | DinD pod daemon config | +| runtime.engine | object | `{"affinity":{},"command":["npm","run","start"],"env":{"CONTAINER_LOGGER_EXEC_CHECK_INTERVAL_MS":1000,"DOCKER_REQUEST_TIMEOUT_MS":30000,"FORCE_COMPOSE_SERIAL_PULL":false,"LOGGER_LEVEL":"debug","LOG_OUTGOING_HTTP_REQUESTS":false,"METRICS_PROMETHEUS_COLLECT_PROCESS_METRICS":false,"METRICS_PROMETHEUS_ENABLED":true,"METRICS_PROMETHEUS_ENABLE_LEGACY_METRICS":false,"METRICS_PROMETHEUS_HOST":"0.0.0.0","METRICS_PROMETHEUS_PORT":9100},"image":{"pullPolicy":"IfNotPresent","registry":"quay.io","repository":"codefresh/engine","tag":"1.174.7"},"nodeSelector":{},"podAnnotations":{},"podLabels":{},"resources":{"limits":{"cpu":"1000m","memory":"2048Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"runtimeImages":{"COMPOSE_IMAGE":"quay.io/codefresh/compose:v2.28.1-1.5.0","CONTAINER_LOGGER_IMAGE":"quay.io/codefresh/cf-container-logger:1.11.6","COSIGN_IMAGE_SIGNER_IMAGE":"quay.io/codefresh/cf-cosign-image-signer:2.4.0-cf.2","CR_6177_FIXER":"quay.io/codefresh/alpine:edge","DOCKER_BUILDER_IMAGE":"quay.io/codefresh/cf-docker-builder:1.3.13","DOCKER_PULLER_IMAGE":"quay.io/codefresh/cf-docker-puller:8.0.17","DOCKER_PUSHER_IMAGE":"quay.io/codefresh/cf-docker-pusher:6.0.16","DOCKER_TAG_PUSHER_IMAGE":"quay.io/codefresh/cf-docker-tag-pusher:1.3.14","FS_OPS_IMAGE":"quay.io/codefresh/fs-ops:1.2.3","GC_BUILDER_IMAGE":"quay.io/codefresh/cf-gc-builder:0.5.3","GIT_CLONE_IMAGE":"quay.io/codefresh/cf-git-cloner:10.1.28","KUBE_DEPLOY":"quay.io/codefresh/cf-deploy-kubernetes:16.1.11","PIPELINE_DEBUGGER_IMAGE":"quay.io/codefresh/cf-debugger:1.3.0","TEMPLATE_ENGINE":"quay.io/codefresh/pikolo:0.14.1"},"schedulerName":"","serviceAccount":"codefresh-engine","tolerations":[],"userEnvVars":[],"workflowLimits":{"MAXIMUM_ALLOWED_TIME_BEFORE_PRE_STEPS_SUCCESS":600,"MAXIMUM_ALLOWED_WORKFLOW_AGE_BEFORE_TERMINATION":86400,"MAXIMUM_ELECTED_STATE_AGE_ALLOWED":900,"MAXIMUM_RETRY_ATTEMPTS_ALLOWED":20,"MAXIMUM_TERMINATING_STATE_AGE_ALLOWED":900,"MAXIMUM_TERMINATING_STATE_AGE_ALLOWED_WITHOUT_UPDATE":300,"TIME_ENGINE_INACTIVE_UNTIL_TERMINATION":300,"TIME_ENGINE_INACTIVE_UNTIL_UNHEALTHY":60,"TIME_INACTIVE_UNTIL_TERMINATION":2700}}` | Parameters for Engine pod (aka "pipeline" orchestrator). | +| runtime.engine.affinity | object | `{}` | Set affinity | +| runtime.engine.command | list | `["npm","run","start"]` | Set container command. | +| runtime.engine.env | object | `{"CONTAINER_LOGGER_EXEC_CHECK_INTERVAL_MS":1000,"DOCKER_REQUEST_TIMEOUT_MS":30000,"FORCE_COMPOSE_SERIAL_PULL":false,"LOGGER_LEVEL":"debug","LOG_OUTGOING_HTTP_REQUESTS":false,"METRICS_PROMETHEUS_COLLECT_PROCESS_METRICS":false,"METRICS_PROMETHEUS_ENABLED":true,"METRICS_PROMETHEUS_ENABLE_LEGACY_METRICS":false,"METRICS_PROMETHEUS_HOST":"0.0.0.0","METRICS_PROMETHEUS_PORT":9100}` | Set additional env vars. | +| runtime.engine.env.CONTAINER_LOGGER_EXEC_CHECK_INTERVAL_MS | int | `1000` | Interval to check the exec status in the container-logger | +| runtime.engine.env.DOCKER_REQUEST_TIMEOUT_MS | int | `30000` | Timeout while doing requests to the Docker daemon | +| runtime.engine.env.FORCE_COMPOSE_SERIAL_PULL | bool | `false` | If "true", composition images will be pulled sequentially | +| runtime.engine.env.LOGGER_LEVEL | string | `"debug"` | Level of logging for engine | +| runtime.engine.env.LOG_OUTGOING_HTTP_REQUESTS | bool | `false` | Enable debug-level logging of outgoing HTTP/HTTPS requests | +| runtime.engine.env.METRICS_PROMETHEUS_COLLECT_PROCESS_METRICS | bool | `false` | Enable collecting process metrics | +| runtime.engine.env.METRICS_PROMETHEUS_ENABLED | bool | `true` | Enable emitting metrics from engine | +| runtime.engine.env.METRICS_PROMETHEUS_ENABLE_LEGACY_METRICS | bool | `false` | Enable legacy metrics | +| runtime.engine.env.METRICS_PROMETHEUS_HOST | string | `"0.0.0.0"` | Host for Prometheus metrics server | +| runtime.engine.env.METRICS_PROMETHEUS_PORT | int | `9100` | Port for Prometheus metrics server | +| runtime.engine.image | object | `{"pullPolicy":"IfNotPresent","registry":"quay.io","repository":"codefresh/engine","tag":"1.174.7"}` | Set image. | +| runtime.engine.nodeSelector | object | `{}` | Set node selector. | +| runtime.engine.podAnnotations | object | `{}` | Set pod annotations. | +| runtime.engine.podLabels | object | `{}` | Set pod labels. | +| runtime.engine.resources | object | `{"limits":{"cpu":"1000m","memory":"2048Mi"},"requests":{"cpu":"100m","memory":"128Mi"}}` | Set resources. | +| runtime.engine.runtimeImages | object | See below. | Set system(base) runtime images. | +| runtime.engine.schedulerName | string | `""` | Set scheduler name. | +| runtime.engine.serviceAccount | string | `"codefresh-engine"` | Set service account for pod. | +| runtime.engine.tolerations | list | `[]` | Set tolerations. | +| runtime.engine.userEnvVars | list | `[]` | Set extra env vars | +| runtime.engine.workflowLimits | object | `{"MAXIMUM_ALLOWED_TIME_BEFORE_PRE_STEPS_SUCCESS":600,"MAXIMUM_ALLOWED_WORKFLOW_AGE_BEFORE_TERMINATION":86400,"MAXIMUM_ELECTED_STATE_AGE_ALLOWED":900,"MAXIMUM_RETRY_ATTEMPTS_ALLOWED":20,"MAXIMUM_TERMINATING_STATE_AGE_ALLOWED":900,"MAXIMUM_TERMINATING_STATE_AGE_ALLOWED_WITHOUT_UPDATE":300,"TIME_ENGINE_INACTIVE_UNTIL_TERMINATION":300,"TIME_ENGINE_INACTIVE_UNTIL_UNHEALTHY":60,"TIME_INACTIVE_UNTIL_TERMINATION":2700}` | Set workflow limits. | +| runtime.engine.workflowLimits.MAXIMUM_ALLOWED_TIME_BEFORE_PRE_STEPS_SUCCESS | int | `600` | Maximum time allowed to the engine to wait for the pre-steps (aka "Initializing Process") to succeed; seconds. | +| runtime.engine.workflowLimits.MAXIMUM_ALLOWED_WORKFLOW_AGE_BEFORE_TERMINATION | int | `86400` | Maximum time for workflow execution; seconds. | +| runtime.engine.workflowLimits.MAXIMUM_ELECTED_STATE_AGE_ALLOWED | int | `900` | Maximum time allowed to workflow to spend in "elected" state; seconds. | +| runtime.engine.workflowLimits.MAXIMUM_RETRY_ATTEMPTS_ALLOWED | int | `20` | Maximum retry attempts allowed for workflow. | +| runtime.engine.workflowLimits.MAXIMUM_TERMINATING_STATE_AGE_ALLOWED | int | `900` | Maximum time allowed to workflow to spend in "terminating" state until force terminated; seconds. | +| runtime.engine.workflowLimits.MAXIMUM_TERMINATING_STATE_AGE_ALLOWED_WITHOUT_UPDATE | int | `300` | Maximum time allowed to workflow to spend in "terminating" state without logs activity until force terminated; seconds. | +| runtime.engine.workflowLimits.TIME_ENGINE_INACTIVE_UNTIL_TERMINATION | int | `300` | Time since the last health check report after which workflow is terminated; seconds. | +| runtime.engine.workflowLimits.TIME_ENGINE_INACTIVE_UNTIL_UNHEALTHY | int | `60` | Time since the last health check report after which the engine is considered unhealthy; seconds. | +| runtime.engine.workflowLimits.TIME_INACTIVE_UNTIL_TERMINATION | int | `2700` | Time since the last workflow logs activity after which workflow is terminated; seconds. | +| runtime.gencerts | object | See below | Parameters for `gencerts-dind` post-upgrade/install hook | +| runtime.inCluster | bool | `true` | (for On-Premise only) Set inCluster runtime | +| runtime.patch | object | See below | Parameters for `runtime-patch` post-upgrade/install hook | +| runtime.rbac | object | `{"create":true,"rules":[]}` | RBAC parameters | +| runtime.rbac.create | bool | `true` | Create RBAC resources | +| runtime.rbac.rules | list | `[]` | Add custom rule to the engine role | +| runtime.runtimeExtends | list | `["system/default/hybrid/k8s_low_limits"]` | Set parent runtime to inherit. Should not be changes. Parent runtime is controlled from Codefresh side. | +| runtime.serviceAccount | object | `{"annotations":{},"create":true}` | Set annotation on engine Service Account Ref: https://codefresh.io/docs/docs/administration/codefresh-runner/#injecting-aws-arn-roles-into-the-cluster | +| serviceMonitor | object | See below | Add serviceMonitor | +| serviceMonitor.main.enabled | bool | `false` | Enable service monitor for dind pods | +| storage.azuredisk.cachingMode | string | `"None"` | | +| storage.azuredisk.skuName | string | `"Premium_LRS"` | Set storage type (`Premium_LRS`) | +| storage.backend | string | `"local"` | Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) | +| storage.ebs.accessKeyId | string | `""` | Set AWS_ACCESS_KEY_ID for volume-provisioner (optional) Ref: https://codefresh.io/docs/docs/installation/codefresh-runner/#dind-volume-provisioner-permissions | +| storage.ebs.accessKeyIdSecretKeyRef | object | `{}` | Existing secret containing AWS_ACCESS_KEY_ID. | +| storage.ebs.availabilityZone | string | `"us-east-1a"` | Set EBS volumes availability zone (required) | +| storage.ebs.encrypted | string | `"false"` | Enable encryption (optional) | +| storage.ebs.kmsKeyId | string | `""` | Set KMS encryption key ID (optional) | +| storage.ebs.secretAccessKey | string | `""` | Set AWS_SECRET_ACCESS_KEY for volume-provisioner (optional) Ref: https://codefresh.io/docs/docs/installation/codefresh-runner/#dind-volume-provisioner-permissions | +| storage.ebs.secretAccessKeySecretKeyRef | object | `{}` | Existing secret containing AWS_SECRET_ACCESS_KEY | +| storage.ebs.volumeType | string | `"gp2"` | Set EBS volume type (`gp2`/`gp3`/`io1`) (required) | +| storage.fsType | string | `"ext4"` | Set filesystem type (`ext4`/`xfs`) | +| storage.gcedisk.availabilityZone | string | `"us-west1-a"` | Set GCP volume availability zone | +| storage.gcedisk.serviceAccountJson | string | `""` | Set Google SA JSON key for volume-provisioner (optional) | +| storage.gcedisk.serviceAccountJsonSecretKeyRef | object | `{}` | Existing secret containing containing Google SA JSON key for volume-provisioner (optional) | +| storage.gcedisk.volumeType | string | `"pd-ssd"` | Set GCP volume backend type (`pd-ssd`/`pd-standard`) | +| storage.local.volumeParentDir | string | `"/var/lib/codefresh/dind-volumes"` | Set volume path on the host filesystem | +| storage.mountAzureJson | bool | `false` | | +| volumeProvisioner | object | See below | Volume Provisioner parameters | +| volumeProvisioner.affinity | object | `{}` | Set affinity | +| volumeProvisioner.dind-lv-monitor | object | See below | `dind-lv-monitor` DaemonSet parameters (local volumes cleaner) | +| volumeProvisioner.enabled | bool | `true` | Enable volume-provisioner | +| volumeProvisioner.env | object | `{}` | Add additional env vars | +| volumeProvisioner.image | object | `{"registry":"quay.io","repository":"codefresh/dind-volume-provisioner","tag":"1.35.0"}` | Set image | +| volumeProvisioner.nodeSelector | object | `{}` | Set node selector | +| volumeProvisioner.podAnnotations | object | `{}` | Set pod annotations | +| volumeProvisioner.podSecurityContext | object | See below | Set security context for the pod | +| volumeProvisioner.rbac | object | `{"create":true,"rules":[]}` | RBAC parameters | +| volumeProvisioner.rbac.create | bool | `true` | Create RBAC resources | +| volumeProvisioner.rbac.rules | list | `[]` | Add custom rule to the role | +| volumeProvisioner.replicasCount | int | `1` | Set number of pods | +| volumeProvisioner.resources | object | `{}` | Set resources | +| volumeProvisioner.serviceAccount | object | `{"annotations":{},"create":true,"name":""}` | Service Account parameters | +| volumeProvisioner.serviceAccount.annotations | object | `{}` | Additional service account annotations | +| volumeProvisioner.serviceAccount.create | bool | `true` | Create service account | +| volumeProvisioner.serviceAccount.name | string | `""` | Override service account name | +| volumeProvisioner.tolerations | list | `[]` | Set tolerations | +| volumeProvisioner.updateStrategy | object | `{"type":"Recreate"}` | Upgrade strategy | + diff --git a/charts/codefresh/cf-runtime/6.3.58/README.md.gotmpl b/charts/codefresh/cf-runtime/6.3.58/README.md.gotmpl new file mode 100644 index 000000000..96e5ca574 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/README.md.gotmpl @@ -0,0 +1,1007 @@ +## Codefresh Runner + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +Helm chart for deploying [Codefresh Runner](https://codefresh.io/docs/docs/installation/codefresh-runner/) to Kubernetes. + +## Table of Content + +- [Prerequisites](#prerequisites) +- [Get Chart Info](#get-chart-info) +- [Install Chart](#install-chart) +- [Chart Configuration](#chart-configuration) +- [Upgrade Chart](#upgrade-chart) + - [To 2.x](#to-2-x) + - [To 3.x](#to-3-x) + - [To 4.x](#to-4-x) + - [To 5.x](#to-5-x) + - [To 6.x](#to-6-x) +- [Architecture](#architecture) +- [Configuration](#configuration) + - [EBS backend volume configuration in AWS](#ebs-backend-volume-configuration) + - [Azure Disks backend volume configuration in AKS](#azure-disks-backend-volume-configuration) + - [GCE Disks backend volume configuration in GKE](#gce-disks-backend-volume-configuration-in-gke) + - [Custom volume mounts](#custom-volume-mounts) + - [Custom global environment variables](#custom-global-environment-variables) + - [Volume reuse policy](#volume-reuse-policy) + - [Volume cleaners](#volume-cleaners) + - [Rootless DinD](#rootless-dind) + - [ARM](#arm) + - [Openshift](#openshift) + - [On-premise](#on-premise) + +## Prerequisites + +- Kubernetes **1.19+** +- Helm **3.8.0+** + +⚠️⚠️⚠️ +> Since version 6.2.x chart is pushed **only** to OCI registry at `oci://quay.io/codefresh/cf-runtime` + +> Versions prior to 6.2.x are still available in ChartMuseum at `http://chartmuseum.codefresh.io/cf-runtime` + +## Get Chart Info + +```console +helm show all oci://quay.io/codefresh/cf-runtime +``` +See [Use OCI-based registries](https://helm.sh/docs/topics/registries/) + +## Install Chart + +**Important:** only helm3 is supported + +- Specify the following mandatory values + +`values.yaml` +```yaml +# -- Global parameters +# @default -- See below +global: + # -- User token in plain text (required if `global.codefreshTokenSecretKeyRef` is omitted!) + # Ref: https://g.codefresh.io/user/settings (see API Keys) + # Minimal API key scopes: Runner-Installation(read+write), Agent(read+write), Agents(read+write) + codefreshToken: "" + # -- User token that references an existing secret containing API key (required if `global.codefreshToken` is omitted!) + codefreshTokenSecretKeyRef: {} + # E.g. + # codefreshTokenSecretKeyRef: + # name: my-codefresh-api-token + # key: codefresh-api-token + + # -- Account ID (required!) + # Can be obtained here https://g.codefresh.io/2.0/account-settings/account-information + accountId: "" + + # -- K8s context name (required!) + context: "" + # E.g. + # context: prod-ue1-runtime-1 + + # -- Agent Name (optional!) + # If omitted, the following format will be used '{{ `{{ .Values.global.context }}_{{ .Release.Namespace }}` }}' + agentName: "" + # E.g. + # agentName: prod-ue1-runtime-1 + + # -- Runtime name (optional!) + # If omitted, the following format will be used '{{ `{{ .Values.global.context }}/{{ .Release.Namespace }}` }}' + runtimeName: "" + # E.g. + # runtimeName: prod-ue1-runtime-1/namespace +``` + +- Install chart + +```console +helm upgrade --install cf-runtime oci://quay.io/codefresh/cf-runtime -f values.yaml --create-namespace --namespace codefresh +``` + +## Chart Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). + +## Upgrade Chart + +### To 2.x + +This major release renames and deprecated several values in the chart. Most of the workload templates have been refactored. + +Affected values: +- `dockerRegistry` is deprecated. Replaced with `global.imageRegistry` +- `re` is renamed to `runtime` +- `storage.localVolumeMonitor` is replaced with `volumeProvisioner.dind-lv-monitor` +- `volumeProvisioner.volume-cleanup` is replaced with `volumeProvisioner.dind-volume-cleanup` +- `image` values structure has been updated. Split to `image.registry` `image.repository` `image.tag` +- pod's `annotations` is renamed to `podAnnotations` + +### To 3.x + +⚠️⚠️⚠️ +### READ this before the upgrade! + +This major release adds [runtime-environment](https://codefresh.io/docs/docs/installation/codefresh-runner/#runtime-environment-specification) spec into chart templates. +That means it is possible to set parametes for `dind` and `engine` pods via [values.yaml](./values.yaml). + +**If you had any overrides (i.e. tolerations/nodeSelector/environment variables/etc) added in runtime spec via [codefresh CLI](https://codefresh-io.github.io/cli/) (for example, you did use [get](https://codefresh-io.github.io/cli/runtime-environments/get-runtime-environments/) and [patch](https://codefresh-io.github.io/cli/runtime-environments/apply-runtime-environments/) commands to modify the runtime-environment), you MUST add these into chart's [values.yaml](./values.yaml) for `.Values.runtime.dind` or(and) .`Values.runtime.engine`** + +**For backward compatibility, you can disable updating runtime-environment spec via** `.Values.runtime.patch.enabled=false` + +Affected values: +- added **mandatory** `global.codefreshToken`/`global.codefreshTokenSecretKeyRef` **You must specify it before the upgrade!** +- `runtime.engine` is added +- `runtime.dind` is added +- `global.existingAgentToken` is replaced with `global.agentTokenSecretKeyRef` +- `global.existingDindCertsSecret` is replaced with `global.dindCertsSecretRef` + +### To 4.x + +This major release adds **agentless inCluster** runtime mode (relevant only for [Codefresh On-Premises](#on-premise) users) + +Affected values: +- `runtime.agent` / `runtime.inCluster` / `runtime.accounts` / `runtime.description` are added + +### To 5.x + +This major release converts `.runtime.dind.pvcs` from **list** to **dict** + +> 4.x chart's values example: +```yaml +runtime: + dind: + pvcs: + - name: dind + storageClassName: my-storage-class-name + volumeSize: 32Gi + reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName' + reuseVolumeSortOrder: pipeline_id +``` + +> 5.x chart's values example: +```yaml +runtime: + dind: + pvcs: + dind: + name: dind + storageClassName: my-storage-class-name + volumeSize: 32Gi + reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName' + reuseVolumeSortOrder: pipeline_id +``` + +Affected values: +- `.runtime.dind.pvcs` converted from **list** to **dict** + +### To 6.x + +⚠️⚠️⚠️ +### READ this before the upgrade! + +This major release deprecates previously required `codefresh runner init --generate-helm-values-file`. + +Affected values: +- **Replaced** `.monitor.clusterId` with `.global.context` as **mandatory** value! +- **Deprecated** `.global.agentToken` / `.global.agentTokenSecretKeyRef` +- **Removed** `.global.agentId` +- **Removed** `.global.keys` / `.global.dindCertsSecretRef` +- **Removed** `.global.existingAgentToken` / `existingDindCertsSecret` +- **Removed** `.monitor.clusterId` / `.monitor.token` / `.monitor.existingMonitorToken` + +#### Migrate the Helm chart from version 5.x to 6.x + +Given this is the legacy `generated_values.yaml` values: + +> legacy `generated_values.yaml` +```yaml +{ + "appProxy": { + "enabled": false, + }, + "monitor": { + "enabled": false, + "clusterId": "my-cluster-name", + "token": "1234567890" + }, + "global": { + "namespace": "namespace", + "codefreshHost": "https://g.codefresh.io", + "agentToken": "0987654321", + "agentId": "agent-id-here", + "agentName": "my-cluster-name_my-namespace", + "accountId": "my-account-id", + "runtimeName": "my-cluster-name/my-namespace", + "codefreshToken": "1234567890", + "keys": { + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "csr": "-----BEGIN CERTIFICATE REQUEST-----...", + "ca": "-----BEGIN CERTIFICATE-----...", + "serverCert": "-----BEGIN CERTIFICATE-----..." + } + } +} +``` + +Update `values.yaml` for new chart version: + +> For existing installation for backward compatibility `.Values.global.agentToken/agentTokenSecretKeyRef` **must be provided!** For installation from scratch this value is no longer required. + +> updated `values.yaml` +```yaml +global: + codefreshToken: "1234567890" + accountId: "my-account-id" + context: "my-cluster-name" + agentToken: "0987654321" # MANDATORY when migrating from < 6.x chart version ! + agentName: "my-cluster-name_my-namespace" # optional + runtimeName: "my-cluster-name/my-namespace" # optional +``` + +> **Note!** Though it's still possible to update runtime-environment via [get](https://codefresh-io.github.io/cli/runtime-environments/get-runtime-environments/) and [patch](https://codefresh-io.github.io/cli/runtime-environments/apply-runtime-environments/) commands, it's recommended to enable sidecar container to pull runtime spec from Codefresh API to detect any drift in configuration. + +```yaml +runner: + # -- Sidecar container + # Reconciles runtime spec from Codefresh API for drift detection + sidecar: + enabled: true +``` + +## Architecture + +[Codefresh Runner architecture](https://codefresh.io/docs/docs/installation/codefresh-runner/#codefresh-runner-architecture) + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). + +### EBS backend volume configuration + +`dind-volume-provisioner` should have permissions to create/attach/detach/delete/get EBS volumes + +Minimal IAM policy for `dind-volume-provisioner` + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AttachVolume", + "ec2:CreateSnapshot", + "ec2:CreateTags", + "ec2:CreateVolume", + "ec2:DeleteSnapshot", + "ec2:DeleteTags", + "ec2:DeleteVolume", + "ec2:DescribeInstances", + "ec2:DescribeSnapshots", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DetachVolume" + ], + "Resource": "*" + } + ] +} +``` + +There are three options: + +1. Run `dind-volume-provisioner` pod on the node/node-group with IAM role + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: ebs-csi + + ebs: + availabilityZone: "us-east-1a" + +volumeProvisioner: + # -- Set node selector + nodeSelector: {} + # -- Set tolerations + tolerations: [] +``` + +2. Pass static credentials in `.Values.storage.ebs.accessKeyId/accessKeyIdSecretKeyRef` and `.Values.storage.ebs.secretAccessKey/secretAccessKeySecretKeyRef` + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: ebs-csi + + ebs: + availabilityZone: "us-east-1a" + + # -- Set AWS_ACCESS_KEY_ID for volume-provisioner (optional) + accessKeyId: "" + # -- Existing secret containing AWS_ACCESS_KEY_ID. + accessKeyIdSecretKeyRef: {} + # E.g. + # accessKeyIdSecretKeyRef: + # name: + # key: + + # -- Set AWS_SECRET_ACCESS_KEY for volume-provisioner (optional) + secretAccessKey: "" + # -- Existing secret containing AWS_SECRET_ACCESS_KEY + secretAccessKeySecretKeyRef: {} + # E.g. + # secretAccessKeySecretKeyRef: + # name: + # key: +``` + +3. Assign IAM role to `dind-volume-provisioner` service account + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: ebs-csi + + ebs: + availabilityZone: "us-east-1a" + +volumeProvisioner: + # -- Service Account parameters + serviceAccount: + # -- Create service account + create: true + # -- Additional service account annotations + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam:::role/" +``` + +### Custom volume mounts + +You can add your own volumes and volume mounts in the runtime environment, so that all pipeline steps will have access to the same set of external files. + +```yaml +runtime: + dind: + userVolumes: + regctl-docker-registry: + name: regctl-docker-registry + secret: + items: + - key: .dockerconfigjson + path: config.json + secretName: regctl-docker-registry + optional: true + userVolumeMounts: + regctl-docker-registry: + name: regctl-docker-registry + mountPath: /home/appuser/.docker/ + readOnly: true + +``` + +### Azure Disks backend volume configuration + +`dind-volume-provisioner` should have permissions to create/delete/get Azure Disks + +Role definition for `dind-volume-provisioner` + +`dind-volume-provisioner-role.json` +```json +{ + "Name": "CodefreshDindVolumeProvisioner", + "Description": "Perform create/delete/get disks", + "IsCustom": true, + "Actions": [ + "Microsoft.Compute/disks/read", + "Microsoft.Compute/disks/write", + "Microsoft.Compute/disks/delete" + + ], + "AssignableScopes": ["/subscriptions/"] +} +``` + +When creating an AKS cluster in Azure there is the option to use a [managed identity](https://learn.microsoft.com/en-us/azure/aks/use-managed-identity) that is assigned to the kubelet. This identity is assigned to the underlying node pool in the AKS cluster and can then be used by the dind-volume-provisioner. + +```console +export ROLE_DEFINITIN_FILE=dind-volume-provisioner-role.json +export SUBSCRIPTION_ID=$(az account show --query "id" | xargs echo ) +export RESOURCE_GROUP= +export AKS_NAME= +export LOCATION=$(az aks show -g $RESOURCE_GROUP -n $AKS_NAME --query location | xargs echo) +export NODES_RESOURCE_GROUP=MC_${RESOURCE_GROUP}_${AKS_NAME}_${LOCATION} +export NODE_SERVICE_PRINCIPAL=$(az aks show -g $RESOURCE_GROUP -n $AKS_NAME --query identityProfile.kubeletidentity.objectId | xargs echo) + +az role definition create --role-definition @${ROLE_DEFINITIN_FILE} +az role assignment create --assignee $NODE_SERVICE_PRINCIPAL --scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$NODES_RESOURCE_GROUP --role CodefreshDindVolumeProvisioner +``` + +Deploy Helm chart with the following values: + +`values.yaml` +```yaml +volumeProvisioner: + podSecurityContext: + enabled: true + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + +storage: + backend: azuredisk + azuredisk: + availabilityZone: northeurope-1 # replace with your zone + resourceGroup: my-resource-group-name + + mountAzureJson: true + +runtime: + dind: + nodeSelector: + topology.kubernetes.io/zone: northeurope-1 +``` + +### GCE Disks backend volume configuration in GKE + +`dind-volume-provisioner` should have `ComputeEngine.StorageAdmin` permissions + +There are three options: + +1. Run `dind-volume-provisioner` pod on the node/node-group with IAM Service Account + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: gcedisk + + gcedisk: + # -- Set GCP volume backend type (`pd-ssd`/`pd-standard`) + volumeType: "pd-standard" + # -- Set GCP volume availability zone + availabilityZone: "us-central1-c" + +volumeProvisioner: + # -- Set node selector + nodeSelector: {} + # -- Set tolerations + tolerations: [] + +# -- Set runtime parameters +runtime: + # -- Parameters for DinD (docker-in-docker) pod + dind: + # -- Set node selector. + nodeSelector: + topology.kubernetes.io/zone: us-central1-c +``` + +2. Pass static credentials in `.Values.storage.gcedisk.serviceAccountJson` (inline) or `.Values.storage.gcedisk.serviceAccountJsonSecretKeyRef` (from your own secret) + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: gcedisk + + gcedisk: + # -- Set GCP volume backend type (`pd-ssd`/`pd-standard`) + volumeType: "`pd-standard" + # -- Set GCP volume availability zone + availabilityZone: "us-central1-c" + # -- Set Google SA JSON key for volume-provisioner (optional) + serviceAccountJson: | + { + "type": "service_account", + "project_id": "...", + "private_key_id": "...", + "private_key": "...", + "client_email": "...", + "client_id": "...", + "auth_uri": "...", + "token_uri": "...", + "auth_provider_x509_cert_url": "...", + "client_x509_cert_url": "..." + } + # -- Existing secret containing containing Google SA JSON key for volume-provisioner (optional) + serviceAccountJsonSecretKeyRef: {} + # E.g.: + # serviceAccountJsonSecretKeyRef: + # name: gce-service-account + # key: service-account.json + +# -- Set runtime parameters +runtime: + # -- Parameters for DinD (docker-in-docker) pod + dind: + # -- Set node selector. + nodeSelector: + topology.kubernetes.io/zone: us-central1-c +``` + +3. Assign IAM role to `dind-volume-provisioner` service account + +```yaml +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: gcedisk + + gcedisk: + # -- Set GCP volume backend type (`pd-ssd`/`pd-standard`) + volumeType: "`pd-standard" + # -- Set GCP volume availability zone + availabilityZone: "us-central1-c" + +volumeProvisioner: + # -- Service Account parameters + serviceAccount: + # -- Create service account + create: true + # -- Additional service account annotations + annotations: + iam.gke.io/gcp-service-account: @.iam.gserviceaccount.com + +# -- Set runtime parameters +runtime: + # -- Parameters for DinD (docker-in-docker) pod + dind: + # -- Set node selector. + nodeSelector: + topology.kubernetes.io/zone: us-central1-c +``` + +### Custom global environment variables + +You can add your own environment variables to the runtime environment. All pipeline steps have access to the global variables. + +```yaml +runtime: + engine: + userEnvVars: + - name: GITHUB_TOKEN + valueFrom: + secretKeyRef: + name: github-token + key: token +``` + +### Volume reuse policy + +Volume reuse behavior depends on the configuration for `reuseVolumeSelector` in the runtime environment spec. + +```yaml +runtime: + dind: + pvcs: + - name: dind + ... + reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName' + reuseVolumeSortOrder: pipeline_id +``` + +The following options are available: +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName'` - PV can be used by ANY pipeline in the specified account (default). +Benefit: Fewer PVs, resulting in lower costs. Since any PV can be used by any pipeline, the cluster needs to maintain/reserve fewer PVs in its PV pool for Codefresh. +Downside: Since the PV can be used by any pipeline, the PVs could have assets and info from different pipelines, reducing the probability of cache. + +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName,project_id'` - PV can be used by ALL pipelines in your account, assigned to the same project. + +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName,pipeline_id'` - PV can be used only by a single pipeline. +Benefit: More probability of cache without “spam” from other pipelines. +Downside: More PVs to maintain and therefore higher costs. + +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName,pipeline_id,io.codefresh.branch_name'` - PV can be used only by single pipeline AND single branch. + +- `reuseVolumeSelector: 'codefresh-app,io.codefresh.accountName,pipeline_id,trigger'` - PV can be used only by single pipeline AND single trigger. + +### Volume cleaners + +Codefresh pipelines require disk space for: + * [Pipeline Shared Volume](https://codefresh.io/docs/docs/pipelines/introduction-to-codefresh-pipelines/#sharing-the-workspace-between-build-steps) (`/codefresh/volume`, implemented as [docker volume](https://docs.docker.com/storage/volumes/)) + * Docker containers, both running and stopped + * Docker images and cached layers + +Codefresh offers two options to manage disk space and prevent out-of-space errors: +* Use runtime cleaners on Docker images and volumes +* [Set the minimum disk space per pipeline build volume](https://codefresh.io/docs/docs/pipelines/pipelines/#set-minimum-disk-space-for-a-pipeline-build) + +To improve performance by using Docker cache, Codefresh `volume-provisioner` can provision previously used disks with Docker images and pipeline volumes from previously run builds. + +### Types of runtime volume cleaners + +Docker images and volumes must be cleaned on a regular basis. + +* [IN-DIND cleaner](https://github.com/codefresh-io/dind/tree/master/cleaner): Deletes extra Docker containers, volumes, and images in **DIND pod**. +* [External volume cleaner](https://github.com/codefresh-io/dind-volume-cleanup): Deletes unused **external** PVs (EBS, GCE/Azure disks). +* [Local volume cleaner](https://github.com/codefresh-io/dind-volume-utils/blob/master/local-volumes/lv-cleaner.sh): Deletes **local** volumes if node disk space is close to the threshold. + +### IN-DIND cleaner + +**Purpose:** Removes unneeded *docker containers, images, volumes* inside Kubernetes volume mounted on the DIND pod + +**How it runs:** Inside each DIND pod as script + +**Triggered by:** SIGTERM and also during the run when disk usage > 90% (configurable) + +**Configured by:** Environment Variables which can be set in Runtime Environment spec + +**Configuration/Logic:** [README.md](https://github.com/codefresh-io/dind/tree/master/cleaner#readme) + +Override `.Values.runtime.dind.env` if necessary (the following are **defaults**): + +```yaml +runtime: + dind: + env: + CLEAN_PERIOD_SECONDS: '21600' # launch clean if last clean was more than CLEAN_PERIOD_SECONDS seconds ago + CLEAN_PERIOD_BUILDS: '5' # launch clean if last clean was more CLEAN_PERIOD_BUILDS builds since last build + IMAGE_RETAIN_PERIOD: '14400' # do not delete docker images if they have events since current_timestamp - IMAGE_RETAIN_PERIOD + VOLUMES_RETAIN_PERIOD: '14400' # do not delete docker volumes if they have events since current_timestamp - VOLUMES_RETAIN_PERIOD + DISK_USAGE_THRESHOLD: '0.8' # launch clean based on current disk usage DISK_USAGE_THRESHOLD + INODES_USAGE_THRESHOLD: '0.8' # launch clean based on current inodes usage INODES_USAGE_THRESHOLD +``` + +### External volumes cleaner + +**Purpose:** Removes unused *kubernetes volumes and related backend volumes* + +**How it runs:** Runs as `dind-volume-cleanup` CronJob. Installed in case the Runner uses non-local volumes `.Values.storage.backend != local` + +**Triggered by:** CronJob every 10min (configurable) + +**Configuration:** + +Set `codefresh.io/volume-retention` for dinds' PVCs: + +```yaml +runtime: + dind: + pvcs: + dind: + ... + annotations: + codefresh.io/volume-retention: 7d +``` + +Or override environment variables for `dind-volume-cleanup` cronjob: + +```yaml +volumeProvisioner: + dind-volume-cleanup: + env: + RETENTION_DAYS: 7 # clean volumes that were last used more than `RETENTION_DAYS` (default is 4) ago +``` + +### Local volumes cleaner + +**Purpose:** Deletes local volumes when node disk space is close to the threshold + +**How it runs:** Runs as `dind-lv-monitor` DaemonSet. Installed in case the Runner uses local volumes `.Values.storage.backend == local` + +**Triggered by:** Disk space usage or inode usage that exceeds thresholds (configurable) + +**Configuration:** + +Override environment variables for `dind-lv-monitor` daemonset: + +```yaml +volumeProvisioner: + dind-lv-monitor: + env: + KB_USAGE_THRESHOLD: 60 # default 80 (percentage) + INODE_USAGE_THRESHOLD: 60 # default 80 +``` + +### Rootless DinD + +DinD pod runs a `priviliged` container with **rootfull** docker. +To run the docker daemon as non-root user (**rootless** mode), change dind image tag: + +`values.yaml` +```yaml +runtime: + dind: + image: + tag: rootless +``` + +### ARM + +With the Codefresh Runner, you can run native ARM64v8 builds. + +> **Note!** +> You cannot run both amd64 and arm64 images within the same pipeline. As one pipeline can map only to one runtime, you can run either amd64 or arm64 within the same pipeline. + +Provide `nodeSelector` and(or) `tolerations` for dind pods: + +`values.yaml` +```yaml +runtime: + dind: + nodeSelector: + arch: arm64 + tolerations: + - key: arch + operator: Equal + value: arm64 + effect: NoSchedule +``` + +### Openshift + +To install Codefresh Runner on OpenShift use the following `values.yaml` example + +```yaml +runner: + podSecurityContext: + enabled: false + +volumeProvisioner: + podSecurityContext: + enabled: false + env: + PRIVILEGED_CONTAINER: true + dind-lv-monitor: + containerSecurityContext: + enabled: true + privileged: true + volumePermissions: + enabled: true + securityContext: + privileged: true + runAsUser: auto +``` + +Grant `privileged` SCC to `cf-runtime-runner` and `cf-runtime-volume-provisioner` service accounts. + +```console +oc adm policy add-scc-to-user privileged system:serviceaccount:codefresh:cf-runtime-runner + +oc adm policy add-scc-to-user privileged system:serviceaccount:codefresh:cf-runtime-volume-provisioner +``` + +### On-premise + +If you have [Codefresh On-Premises](https://artifacthub.io/packages/helm/codefresh-onprem/codefresh) deployed, you can install Codefresh Runner in **agentless** mode. + +**What is agentless mode?** + +Agent (aka venona) is Runner component which responsible for calling Codefresh API to run builds and create dind/engine pods and pvc objects. Agent can only be assigned to a single account, thus you can't share one runtime across multiple accounts. However, with **agentless** mode it's possible to register the runtime as **system**-type runtime so it's registered on the platform level and can be assigned/shared across multiple accounts. + +**What are the prerequisites?** +- You have a running [Codefresh On-Premises](https://artifacthub.io/packages/helm/codefresh-onprem/codefresh) control-plane environment +- You have a Codefresh API token with platform **Admin** permissions scope + + +### How to deploy agentless runtime when it's on the SAME k8s cluster as On-Premises control-plane environment? + +- Enable cluster-level permissions for cf-api (On-Premises control-plane component) + +> `values.yaml` for [Codefresh On-Premises](https://artifacthub.io/packages/helm/codefresh-onprem/codefresh) Helm chart +```yaml +cfapi: + ... + # -- Enable ClusterRole/ClusterRoleBinding + rbac: + namespaced: false +``` + +- Set the following values for Runner Helm chart + +`.Values.global.codefreshHost=...` \ +`.Values.global.codefreshToken=...` \ +`.Values.global.runtimeName=system/...` \ +`.Values.runtime.agent=false` \ +`.Values.runtime.inCluster=true` + +> `values.yaml` for [Codefresh Runner](https://artifacthub.io/packages/helm/codefresh-runner/cf-runtime) helm chart +```yaml +global: + # -- URL of Codefresh On-Premises Platform + codefreshHost: "https://myonprem.somedomain.com" + # -- User token in plain text with Admin permission scope + codefreshToken: "" + # -- User token that references an existing secret containing API key. + codefreshTokenSecretKeyRef: {} + # E.g. + # codefreshTokenSecretKeyRef: + # name: my-codefresh-api-token + # key: codefresh-api-token + + # -- Distinguished runtime name + # (for On-Premise only; mandatory!) Must be prefixed with "system/..." + runtimeName: "system/prod-ue1-some-cluster-name" + +# -- Set runtime parameters +runtime: + # -- (for On-Premise only; mandatory!) Disable agent + agent: false + # -- (for On-Premise only; optional) Set inCluster runtime (default: `true`) + # `inCluster=true` flag is set when Runtime and On-Premises control-plane are run on the same cluster + # `inCluster=false` flag is set when Runtime and On-Premises control-plane are on different clusters + inCluster: true + # -- (for On-Premise only; optional) Assign accounts to runtime (list of account ids; default is empty) + # Accounts can be assigned to the runtime in Codefresh UI later so you can kepp it empty. + accounts: [] + # -- Set parent runtime to inherit. + runtimeExtends: [] +``` + +- Install the chart + +```console +helm upgrade --install cf-runtime oci://quay.io/codefresh/cf-runtime -f values.yaml --create-namespace --namespace cf-runtime +``` + +- Verify the runtime and run test pipeline + +Go to [https:///admin/runtime-environments/system](https:///admin/runtime-environments/system) to check the runtime. Assign it to the required account(s). Run test pipeline on it. + + +### How to deploy agentless runtime when it's on the DIFFERENT k8s cluster than On-Premises control-plane environment? + +In this case, it's required to mount runtime cluster's `KUBECONFIG` into On-Premises `cf-api` deployment + +- Create the neccessary RBAC resources + +> `values.yaml` for [Codefresh Runner](https://artifacthub.io/packages/helm/codefresh-runner/cf-runtime) helm chart +```yaml +extraResources: +- apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: codefresh-role + namespace: '{{ "{{ .Release.Namespace }}" }}' + rules: + - apiGroups: [""] + resources: ["pods", "persistentvolumeclaims", "persistentvolumes"] + verbs: ["list", "watch", "get", "create", "patch", "delete"] + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshots"] + verbs: ["list", "watch", "get", "create", "patch", "delete"] +- apiVersion: v1 + kind: ServiceAccount + metadata: + name: codefresh-runtime-user + namespace: '{{ "{{ .Release.Namespace }}" }}' +- apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: codefresh-runtime-user + namespace: '{{ "{{ .Release.Namespace }}" }}' + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: codefresh-role + subjects: + - kind: ServiceAccount + name: codefresh-runtime-user + namespace: '{{ "{{ .Release.Namespace }}" }}' +- apiVersion: v1 + kind: Secret + metadata: + name: codefresh-runtime-user-token + namespace: '{{ "{{ .Release.Namespace }}" }}' + annotations: + kubernetes.io/service-account.name: codefresh-runtime-user + type: kubernetes.io/service-account-token +``` + +- Set up the following environment variables to create a `KUBECONFIG` file + +```shell +NAMESPACE=cf-runtime +CLUSTER_NAME=prod-ue1-some-cluster-name +CURRENT_CONTEXT=$(kubectl config current-context) + +USER_TOKEN_VALUE=$(kubectl -n cf-runtime get secret/codefresh-runtime-user-token -o=go-template='{{ `{{.data.token}}` }}' | base64 --decode) +CURRENT_CLUSTER=$(kubectl config view --raw -o=go-template='{{ `{{range .contexts}}{{if eq .name "'''${CURRENT_CONTEXT}'''"}}{{ index .context "cluster" }}{{end}}{{end}}` }}') +CLUSTER_CA=$(kubectl config view --raw -o=go-template='{{ `{{range .clusters}}{{if eq .name "'''${CURRENT_CLUSTER}'''"}}"{{with index .cluster "certificate-authority-data" }}{{.}}{{end}}"{{ end }}{{ end }}` }}') +CLUSTER_SERVER=$(kubectl config view --raw -o=go-template='{{ `{{range .clusters}}{{if eq .name "'''${CURRENT_CLUSTER}'''"}}{{ .cluster.server }}{{end}}{{ end }}` }}') + +export -p USER_TOKEN_VALUE CURRENT_CONTEXT CURRENT_CLUSTER CLUSTER_CA CLUSTER_SERVER CLUSTER_NAME +``` + +- Create a kubeconfig file + +```console +cat << EOF > $CLUSTER_NAME-kubeconfig +apiVersion: v1 +kind: Config +current-context: ${CLUSTER_NAME} +contexts: +- name: ${CLUSTER_NAME} + context: + cluster: ${CLUSTER_NAME} + user: codefresh-runtime-user + namespace: ${NAMESPACE} +clusters: +- name: ${CLUSTER_NAME} + cluster: + certificate-authority-data: ${CLUSTER_CA} + server: ${CLUSTER_SERVER} +users: +- name: ${CLUSTER_NAME} + user: + token: ${USER_TOKEN_VALUE} +EOF +``` + +- **Switch context to On-Premises control-plane cluster**. Create k8s secret (via any tool like [ESO](https://external-secrets.io/v0.4.4/), `kubectl`, etc ) containing runtime cluster's `KUBECONFG` created in previous step. + +```shell +NAMESPACE=codefresh +kubectl create secret generic dind-runtime-clusters --from-file=$CLUSTER_NAME=$CLUSTER_NAME-kubeconfig -n $NAMESPACE +``` + +- Mount secret containing runtime cluster's `KUBECONFG` into cf-api in On-Premises control-plane cluster + +> `values.yaml` for [Codefresh On-Premises](https://artifacthub.io/packages/helm/codefresh-onprem/codefresh) helm chart +```yaml +cf-api: + ... + volumes: + dind-clusters: + enabled: true + type: secret + nameOverride: dind-runtime-clusters + optional: true +``` +> volumeMount `/etc/kubeconfig` is already configured in cf-api Helm chart template. No need to specify it. + +- Set the following values for Runner helm chart + +> `values.yaml` for [Codefresh Runner](https://artifacthub.io/packages/helm/codefresh-runner/cf-runtime) helm chart + +`.Values.global.codefreshHost=...` \ +`.Values.global.codefreshToken=...` \ +`.Values.global.runtimeName=system/...` \ +`.Values.runtime.agent=false` \ +`.Values.runtime.inCluster=false` + +**Important!** +`.Values.global.name` ("system/" prefix is ignored!) should match the cluster name (key in `dind-runtime-clusters` secret created previously) +```yaml +global: + # -- URL of Codefresh On-Premises Platform + codefreshHost: "https://myonprem.somedomain.com" + # -- User token in plain text with Admin permission scope + codefreshToken: "" + # -- User token that references an existing secret containing API key. + codefreshTokenSecretKeyRef: {} + # E.g. + # codefreshTokenSecretKeyRef: + # name: my-codefresh-api-token + # key: codefresh-api-token + + # -- Distinguished runtime name + # (for On-Premise only; mandatory!) Must be prefixed with "system/..." + name: "system/prod-ue1-some-cluster-name" + +# -- Set runtime parameters +runtime: + # -- (for On-Premise only; mandatory!) Disable agent + agent: false + # -- (for On-Premise only; optional) Set inCluster runtime (default: `true`) + # `inCluster=true` flag is set when Runtime and On-Premises control-plane are run on the same cluster + # `inCluster=false` flag is set when Runtime and On-Premises control-plane are on different clusters + inCluster: false + # -- (for On-Premise only; optional) Assign accounts to runtime (list of account ids; default is empty) + # Accounts can be assigned to the runtime in Codefresh UI later so you can kepp it empty. + accounts: [] + # -- (optional) Set parent runtime to inherit. + runtimeExtends: [] +``` + +- Install the chart + +```console +helm upgrade --install cf-runtime oci://quay.io/codefresh/cf-runtime -f values.yaml --create-namespace --namespace cf-runtime +``` + +- Verify the runtime and run test pipeline + +Go to [https:///admin/runtime-environments/system](https:///admin/runtime-environments/system) to see the runtime. Assign it to the required account(s). + +{{ template "chart.requirementsSection" . }} + +{{ template "chart.valuesSection" . }} + diff --git a/charts/codefresh/cf-runtime/6.3.58/files/cleanup-runtime.sh b/charts/codefresh/cf-runtime/6.3.58/files/cleanup-runtime.sh new file mode 100644 index 000000000..c1fc5f368 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/files/cleanup-runtime.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +echo "-----" +echo "API_HOST: ${API_HOST}" +echo "AGENT_NAME: ${AGENT_NAME}" +echo "RUNTIME_NAME: ${RUNTIME_NAME}" +echo "AGENT: ${AGENT}" +echo "AGENT_SECRET_NAME: ${AGENT_SECRET_NAME}" +echo "DIND_SECRET_NAME: ${DIND_SECRET_NAME}" +echo "-----" + +auth() { + codefresh auth create-context --api-key ${API_TOKEN} --url ${API_HOST} +} + +remove_runtime() { + if [ "$AGENT" == "true" ]; then + codefresh delete re ${RUNTIME_NAME} || true + else + codefresh delete sys-re ${RUNTIME_NAME} || true + fi +} + +remove_agent() { + codefresh delete agent ${AGENT_NAME} || true +} + +remove_secrets() { + kubectl patch secret $(kubectl get secret -l codefresh.io/internal=true | awk 'NR>1{print $1}' | xargs) -p '{"metadata":{"finalizers":null}}' --type=merge || true + kubectl delete secret $AGENT_SECRET_NAME || true + kubectl delete secret $DIND_SECRET_NAME || true +} + +auth +remove_runtime +remove_agent +remove_secrets \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/files/configure-dind-certs.sh b/charts/codefresh/cf-runtime/6.3.58/files/configure-dind-certs.sh new file mode 100644 index 000000000..a1092eb1e --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/files/configure-dind-certs.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash +# + +#--- +fatal() { + echo "ERROR: $1" + exit 1 +} + +msg() { echo -e "\e[32mINFO ---> $1\e[0m"; } +err() { echo -e "\e[31mERR ---> $1\e[0m" ; return 1; } + +exit_trap () { + local lc="$BASH_COMMAND" rc=$? + if [ $rc != 0 ]; then + if [[ -n "$SLEEP_ON_ERROR" ]]; then + echo -e "\nSLEEP_ON_ERROR is set - Sleeping to fix error" + sleep $SLEEP_ON_ERROR + fi + fi +} +trap exit_trap EXIT + +usage() { + echo "Usage: + $0 [-n | --namespace] [--server-cert-cn] [--server-cert-extra-sans] codefresh-api-host codefresh-api-token + +Example: + $0 -n workflow https://g.codefresh.io 21341234.423141234.412431234 + +" +} + +# Args +while [[ $1 =~ ^(-(n|h)|--(namespace|server-cert-cn|server-cert-extra-sans|help)) ]] +do + key=$1 + value=$2 + + case $key in + -h|--help) + usage + exit + ;; + -n|--namespace) + NAMESPACE="$value" + shift + ;; + --server-cert-cn) + SERVER_CERT_CN="$value" + shift + ;; + --server-cert-extra-sans) + SERVER_CERT_EXTRA_SANS="$value" + shift + ;; + esac + shift # past argument or value +done + +API_HOST=${1:-"$CF_API_HOST"} +API_TOKEN=${2:-"$CF_API_TOKEN"} + +[[ -z "$API_HOST" ]] && usage && fatal "Missing API_HOST" +[[ -z "$API_TOKEN" ]] && usage && fatal "Missing token" + + +API_SIGN_PATH=${API_SIGN_PATH:-"api/custom_clusters/signServerCerts"} + +NAMESPACE=${NAMESPACE:-default} +RELEASE=${RELEASE:-cf-runtime} + +DIR=$(dirname $0) +TMPDIR=/tmp/codefresh/ + +TMP_CERTS_FILE_ZIP=$TMPDIR/cf-certs.zip +TMP_CERTS_HEADERS_FILE=$TMPDIR/cf-certs-response-headers.txt +CERTS_DIR=$TMPDIR/ssl +SRV_TLS_CA_CERT=${CERTS_DIR}/ca.pem +SRV_TLS_KEY=${CERTS_DIR}/server-key.pem +SRV_TLS_CSR=${CERTS_DIR}/server-cert.csr +SRV_TLS_CERT=${CERTS_DIR}/server-cert.pem +CF_SRV_TLS_CERT=${CERTS_DIR}/cf-server-cert.pem +CF_SRV_TLS_CA_CERT=${CERTS_DIR}/cf-ca.pem +mkdir -p $TMPDIR $CERTS_DIR + +K8S_CERT_SECRET_NAME=codefresh-certs-server +echo -e "\n------------------\nGenerating server tls certificates ... " + +SERVER_CERT_CN=${SERVER_CERT_CN:-"docker.codefresh.io"} +SERVER_CERT_EXTRA_SANS="${SERVER_CERT_EXTRA_SANS}" +### + + openssl genrsa -out $SRV_TLS_KEY 4096 || fatal "Failed to generate openssl key " + openssl req -subj "/CN=${SERVER_CERT_CN}" -new -key $SRV_TLS_KEY -out $SRV_TLS_CSR || fatal "Failed to generate openssl csr " + GENERATE_CERTS=true + CSR=$(sed ':a;N;$!ba;s/\n/\\n/g' ${SRV_TLS_CSR}) + + SERVER_CERT_SANS="IP:127.0.0.1,DNS:dind,DNS:*.dind.${NAMESPACE},DNS:*.dind.${NAMESPACE}.svc${KUBE_DOMAIN},DNS:*.cf-cd.com,DNS:*.codefresh.io" + if [[ -n "${SERVER_CERT_EXTRA_SANS}" ]]; then + SERVER_CERT_SANS=${SERVER_CERT_SANS},${SERVER_CERT_EXTRA_SANS} + fi + echo "{\"reqSubjectAltName\": \"${SERVER_CERT_SANS}\", \"csr\": \"${CSR}\" }" > ${TMPDIR}/sign_req.json + + rm -fv ${TMP_CERTS_HEADERS_FILE} ${TMP_CERTS_FILE_ZIP} + + SIGN_STATUS=$(curl -k -sSL -d @${TMPDIR}/sign_req.json -H "Content-Type: application/json" -H "Authorization: ${API_TOKEN}" -H "Expect: " \ + -o ${TMP_CERTS_FILE_ZIP} -D ${TMP_CERTS_HEADERS_FILE} -w '%{http_code}' ${API_HOST}/${API_SIGN_PATH} ) + + echo "Sign request completed with HTTP_STATUS_CODE=$SIGN_STATUS" + if [[ $SIGN_STATUS != 200 ]]; then + echo "ERROR: Cannot sign certificates" + if [[ -f ${TMP_CERTS_FILE_ZIP} ]]; then + mv ${TMP_CERTS_FILE_ZIP} ${TMP_CERTS_FILE_ZIP}.error + cat ${TMP_CERTS_FILE_ZIP}.error + fi + exit 1 + fi + unzip -o -d ${CERTS_DIR}/ ${TMP_CERTS_FILE_ZIP} || fatal "Failed to unzip certificates to ${CERTS_DIR} " + cp -v ${CF_SRV_TLS_CA_CERT} $SRV_TLS_CA_CERT || fatal "received ${TMP_CERTS_FILE_ZIP} does not contains ca.pem" + cp -v ${CF_SRV_TLS_CERT} $SRV_TLS_CERT || fatal "received ${TMP_CERTS_FILE_ZIP} does not contains cf-server-cert.pem" + + +echo -e "\n------------------\nCreating certificate secret " + +kubectl -n $NAMESPACE create secret generic $K8S_CERT_SECRET_NAME \ + --from-file=$SRV_TLS_CA_CERT \ + --from-file=$SRV_TLS_KEY \ + --from-file=$SRV_TLS_CERT \ + --dry-run=client -o yaml | kubectl apply --overwrite -f - +kubectl -n $NAMESPACE label --overwrite secret ${K8S_CERT_SECRET_NAME} codefresh.io/internal=true +kubectl -n $NAMESPACE patch secret $K8S_CERT_SECRET_NAME -p '{"metadata": {"finalizers": ["kubernetes"]}}' diff --git a/charts/codefresh/cf-runtime/6.3.58/files/init-runtime.sh b/charts/codefresh/cf-runtime/6.3.58/files/init-runtime.sh new file mode 100644 index 000000000..eb3488af1 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/files/init-runtime.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +echo "-----" +echo "API_HOST: ${API_HOST}" +echo "AGENT_NAME: ${AGENT_NAME}" +echo "KUBE_CONTEXT: ${KUBE_CONTEXT}" +echo "KUBE_NAMESPACE: ${KUBE_NAMESPACE}" +echo "OWNER_NAME: ${OWNER_NAME}" +echo "RUNTIME_NAME: ${RUNTIME_NAME}" +echo "SECRET_NAME: ${SECRET_NAME}" +echo "-----" + +create_agent_secret() { + + kubectl apply -f - < $1\e[0m"; } +err() { echo -e "\e[31mERR ---> $1\e[0m" ; return 1; } + + +if [ -z "${USER_CODEFRESH_TOKEN}" ]; then + err "missing codefresh user token. must supply \".global.codefreshToken\" if agent-codefresh-token does not exist" + exit 1 +fi + +codefresh auth create-context --api-key ${USER_CODEFRESH_TOKEN} --url ${API_HOST} + +while true; do + msg "Reconciling ${RUNTIME_NAME} runtime" + + sleep $RECONCILE_INTERVAL + + codefresh get re \ + --name ${RUNTIME_NAME} \ + -o yaml \ + | yq 'del(.version, .metadata.changedBy, .metadata.creationTime)' > /tmp/runtime.yaml + + kubectl get cm ${CONFIGMAP_NAME} -n ${KUBE_NAMESPACE} -o yaml \ + | yq 'del(.metadata.resourceVersion, .metadata.uid)' \ + | yq eval '.data["runtime.yaml"] = load_str("/tmp/runtime.yaml")' \ + | kubectl apply -f - +done diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_deployment.yaml new file mode 100644 index 000000000..26f3576b7 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_deployment.yaml @@ -0,0 +1,70 @@ +{{- define "app-proxy.resources.deployment" -}} +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "app-proxy.fullname" . }} + labels: + {{- include "app-proxy.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicasCount }} + strategy: + type: {{ .Values.updateStrategy.type }} + selector: + matchLabels: + {{- include "app-proxy.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "app-proxy.selectorLabels" . | nindent 8 }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- include (printf "%s.image.pullSecrets" $cfCommonTplSemver ) . | nindent 8 }} + serviceAccountName: {{ include "app-proxy.serviceAccountName" . }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + containers: + - name: app-proxy + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.image "context" .) }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "Always" }} + env: + {{- include "app-proxy.environment-variables" . | nindent 8 }} + ports: + - name: http + containerPort: 3000 + readinessProbe: + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + httpGet: + path: /health + port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + volumes: + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_env-vars.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_env-vars.yaml new file mode 100644 index 000000000..c9b9a0e36 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_env-vars.yaml @@ -0,0 +1,19 @@ +{{- define "app-proxy.environment-variables.defaults" }} +PORT: 3000 +{{- end }} + +{{- define "app-proxy.environment-variables.calculated" }} +CODEFRESH_HOST: {{ include "runtime.runtime-environment-spec.codefresh-host" . }} +{{- with .Values.ingress.pathPrefix }} +API_PATH_PREFIX: {{ . | quote }} +{{- end }} +{{- end }} + +{{- define "app-proxy.environment-variables" }} +{{- $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{- $defaults := (include "app-proxy.environment-variables.defaults" . | fromYaml) }} +{{- $calculated := (include "app-proxy.environment-variables.calculated" . | fromYaml) }} +{{- $overrides := .Values.env }} +{{- $mergedValues := mergeOverwrite (merge $defaults $calculated) $overrides }} +{{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $mergedValues "context" .) }} +{{- end }} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_helpers.tpl b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_helpers.tpl new file mode 100644 index 000000000..2d4272ca9 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_helpers.tpl @@ -0,0 +1,43 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "app-proxy.name" -}} + {{- printf "%s-%s" (include "cf-runtime.name" .) "app-proxy" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "app-proxy.fullname" -}} + {{- printf "%s-%s" (include "cf-runtime.fullname" .) "app-proxy" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "app-proxy.labels" -}} +{{ include "cf-runtime.labels" . }} +codefresh.io/application: app-proxy +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "app-proxy.selectorLabels" -}} +{{ include "cf-runtime.selectorLabels" . }} +codefresh.io/application: app-proxy +{{- end }} + + +{{/* +Create the name of the service account to use +*/}} +{{- define "app-proxy.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "app-proxy.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_ingress.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_ingress.yaml new file mode 100644 index 000000000..d7860b363 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_ingress.yaml @@ -0,0 +1,32 @@ +{{- define "app-proxy.resources.ingress" -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "app-proxy.fullname" . }} + labels: {{- include "app-proxy.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.class (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.class }} + {{- end }} + {{- if .Values.ingress.tlsSecret }} + tls: + - hosts: + - {{ .Values.ingress.host }} + secretName: {{ .Values.tlsSecret }} + {{- end }} + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - path: {{ .Values.ingress.pathPrefix | default "/" }} + pathType: ImplementationSpecific + backend: + service: + name: {{ include "app-proxy.fullname" . }} + port: + number: 80 +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_rbac.yaml new file mode 100644 index 000000000..87bd869ba --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_rbac.yaml @@ -0,0 +1,47 @@ +{{- define "app-proxy.resources.rbac" -}} +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "app-proxy.serviceAccountName" . }} + labels: + {{- include "app-proxy.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- +{{- if .Values.rbac.create }} +kind: {{ .Values.rbac.namespaced | ternary "Role" "ClusterRole" }} +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "app-proxy.fullname" . }} + labels: + {{- include "app-proxy.labels" . | nindent 4 }} +rules: + - apiGroups: [ "" ] + resources: [ "secrets" ] + verbs: [ "get" ] +{{- with .Values.rbac.rules }} + {{ toYaml . | nindent 2 }} +{{- end }} +{{- end }} +--- +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +kind: {{ .Values.rbac.namespaced | ternary "RoleBinding" "ClusterRoleBinding" }} +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "app-proxy.fullname" . }} + labels: + {{- include "app-proxy.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "app-proxy.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ include "app-proxy.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_service.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_service.yaml new file mode 100644 index 000000000..4c3a93bf2 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/app-proxy/_service.yaml @@ -0,0 +1,17 @@ +{{- define "app-proxy.resources.service" -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "app-proxy.fullname" . }} + labels: + {{- include "app-proxy.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 3000 + selector: + {{- include "app-proxy.selectorLabels" . | nindent 4 }} +{{- end -}} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_deployment.yaml new file mode 100644 index 000000000..62588b4d3 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_deployment.yaml @@ -0,0 +1,62 @@ +{{- define "event-exporter.resources.deployment" -}} +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "event-exporter.fullname" . }} + labels: + {{- include "event-exporter.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicasCount }} + strategy: + type: {{ .Values.updateStrategy.type }} + selector: + matchLabels: + {{- include "event-exporter.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "event-exporter.selectorLabels" . | nindent 8 }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- include (printf "%s.image.pullSecrets" $cfCommonTplSemver ) . | nindent 8 }} + serviceAccountName: {{ include "event-exporter.serviceAccountName" . }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + containers: + - name: event-exporter + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.image "context" .) }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "Always" }} + args: [--running-in-cluster=true] + env: + {{- include "event-exporter.environment-variables" . | nindent 8 }} + ports: + - name: metrics + containerPort: 9102 + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + volumes: + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_env-vars.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_env-vars.yaml new file mode 100644 index 000000000..d28d0776f --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_env-vars.yaml @@ -0,0 +1,14 @@ +{{- define "event-exporter.environment-variables.defaults" }} +{{- end }} + +{{- define "event-exporter.environment-variables.calculated" }} +{{- end }} + +{{- define "event-exporter.environment-variables" }} +{{- $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{- $defaults := (include "event-exporter.environment-variables.defaults" . | fromYaml) }} +{{- $calculated := (include "event-exporter.environment-variables.calculated" . | fromYaml) }} +{{- $overrides := .Values.env }} +{{- $mergedValues := mergeOverwrite (merge $defaults $calculated) $overrides }} +{{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $mergedValues "context" .) }} +{{- end }} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_helpers.tpl b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_helpers.tpl new file mode 100644 index 000000000..5b8b5eff7 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_helpers.tpl @@ -0,0 +1,43 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "event-exporter.name" -}} + {{- printf "%s-%s" (include "cf-runtime.name" .) "event-exporter" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "event-exporter.fullname" -}} + {{- printf "%s-%s" (include "cf-runtime.fullname" .) "event-exporter" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "event-exporter.labels" -}} +{{ include "cf-runtime.labels" . }} +app: event-exporter +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "event-exporter.selectorLabels" -}} +{{ include "cf-runtime.selectorLabels" . }} +app: event-exporter +{{- end }} + + +{{/* +Create the name of the service account to use +*/}} +{{- define "event-exporter.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "event-exporter.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_rbac.yaml new file mode 100644 index 000000000..69d7b6b2f --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_rbac.yaml @@ -0,0 +1,47 @@ +{{- define "event-exporter.resources.rbac" -}} +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "event-exporter.serviceAccountName" . }} + labels: + {{- include "event-exporter.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- +{{- if .Values.rbac.create }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "event-exporter.fullname" . }} + labels: + {{- include "event-exporter.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: [events] + verbs: [get, list, watch] +{{- with .Values.rbac.rules }} + {{ toYaml . | nindent 2 }} +{{- end }} +{{- end }} +--- +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "event-exporter.fullname" . }} + labels: + {{- include "event-exporter.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "event-exporter.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "event-exporter.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_service.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_service.yaml new file mode 100644 index 000000000..6fa29ec1a --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_service.yaml @@ -0,0 +1,17 @@ +{{- define "event-exporter.resources.service" -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "event-exporter.fullname" . }} + labels: + {{- include "event-exporter.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - name: metrics + port: 9102 + targetPort: metrics + protocol: TCP + selector: + {{- include "event-exporter.selectorLabels" . | nindent 4 }} +{{- end -}} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_serviceMontor.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_serviceMontor.yaml new file mode 100644 index 000000000..6092443f0 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/event-exporter/_serviceMontor.yaml @@ -0,0 +1,14 @@ +{{- define "event-exporter.resources.serviceMonitor" -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "event-exporter.fullname" . }} + labels: + {{- include "event-exporter.labels" . | nindent 4 }} +spec: + endpoints: + - port: metrics + selector: + matchLabels: + {{- include "event-exporter.selectorLabels" . | nindent 6 }} +{{- end -}} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_deployment.yaml new file mode 100644 index 000000000..7efa6557b --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_deployment.yaml @@ -0,0 +1,70 @@ +{{- define "monitor.resources.deployment" -}} +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "monitor.fullname" . }} + labels: + {{- include "monitor.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicasCount }} + strategy: + type: {{ .Values.updateStrategy.type }} + selector: + matchLabels: + {{- include "monitor.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "monitor.selectorLabels" . | nindent 8 }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- include (printf "%s.image.pullSecrets" $cfCommonTplSemver ) . | nindent 8 }} + serviceAccountName: {{ include "monitor.serviceAccountName" . }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + containers: + - name: monitor + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.image "context" .) }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "Always" }} + env: + {{- include "monitor.environment-variables" . | nindent 8 }} + ports: + - name: http + containerPort: 9020 + readinessProbe: + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + httpGet: + path: /api/ping + port: 9020 + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + volumes: + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_env-vars.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_env-vars.yaml new file mode 100644 index 000000000..f58c7fa25 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_env-vars.yaml @@ -0,0 +1,26 @@ +{{- define "monitor.environment-variables.defaults" }} +SERVICE_NAME: {{ include "monitor.fullname" . }} +PORT: 9020 +HELM3: true +NODE_OPTIONS: "--max_old_space_size=4096" +{{- end }} + +{{- define "monitor.environment-variables.calculated" }} +API_TOKEN: {{ include "runtime.installation-token-env-var-value" . | nindent 2 }} +CLUSTER_ID: {{ include "runtime.runtime-environment-spec.context-name" . }} +API_URL: {{ include "runtime.runtime-environment-spec.codefresh-host" . }}/api/k8s-monitor/events +ACCOUNT_ID: {{ .Values.global.accountId }} +NAMESPACE: {{ .Release.Namespace }} +{{- if .Values.rbac.namespaced }} +ROLE_BINDING: true +{{- end }} +{{- end }} + +{{- define "monitor.environment-variables" }} +{{- $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{- $defaults := (include "monitor.environment-variables.defaults" . | fromYaml) }} +{{- $calculated := (include "monitor.environment-variables.calculated" . | fromYaml) }} +{{- $overrides := .Values.env }} +{{- $mergedValues := mergeOverwrite (merge $defaults $calculated) $overrides }} +{{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $mergedValues "context" .) }} +{{- end }} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_helpers.tpl b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_helpers.tpl new file mode 100644 index 000000000..71cc1c027 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_helpers.tpl @@ -0,0 +1,42 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "monitor.name" -}} + {{- printf "%s-%s" (include "cf-runtime.name" .) "monitor" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "monitor.fullname" -}} + {{- printf "%s-%s" (include "cf-runtime.fullname" .) "monitor" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "monitor.labels" -}} +{{ include "cf-runtime.labels" . }} +codefresh.io/application: monitor +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "monitor.selectorLabels" -}} +{{ include "cf-runtime.selectorLabels" . }} +codefresh.io/application: monitor +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "monitor.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "monitor.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_rbac.yaml new file mode 100644 index 000000000..88204796a --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_rbac.yaml @@ -0,0 +1,56 @@ +{{- define "monitor.resources.rbac" -}} +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "monitor.serviceAccountName" . }} + labels: + {{- include "monitor.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- +{{- if .Values.rbac.create }} +kind: {{ .Values.rbac.namespaced | ternary "Role" "ClusterRole" }} +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "monitor.fullname" . }} + labels: + {{- include "monitor.labels" . | nindent 4 }} +rules: + - apiGroups: [ "" ] + resources: [ "*" ] + verbs: [ "get", "list", "watch", "create", "delete" ] + - apiGroups: [ "" ] + resources: [ "pods" ] + verbs: [ "get", "list", "watch", "create", "deletecollection" ] + - apiGroups: [ "extensions" ] + resources: [ "*" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "apps" ] + resources: [ "*" ] + verbs: [ "get", "list", "watch" ] +{{- with .Values.rbac.rules }} + {{ toYaml . | nindent 2 }} +{{- end }} +{{- end }} +--- +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +kind: {{ .Values.rbac.namespaced | ternary "RoleBinding" "ClusterRoleBinding" }} +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "monitor.fullname" . }} + labels: + {{- include "monitor.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "monitor.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: {{ .Values.rbac.namespaced | ternary "Role" "ClusterRole" }} + name: {{ include "monitor.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_service.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_service.yaml new file mode 100644 index 000000000..f6ae9bb0f --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/monitor/_service.yaml @@ -0,0 +1,17 @@ +{{- define "monitor.resources.service" -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "monitor.fullname" . }} + labels: + {{- include "monitor.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 9020 + selector: + {{- include "monitor.selectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_deployment.yaml new file mode 100644 index 000000000..e1fb9439a --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_deployment.yaml @@ -0,0 +1,103 @@ +{{- define "runner.resources.deployment" -}} +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "runner.fullname" . }} + labels: + {{- include "runner.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicasCount }} + strategy: + type: {{ .Values.updateStrategy.type }} + selector: + matchLabels: + {{- include "runner.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "runner.selectorLabels" . | nindent 8 }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- include (printf "%s.image.pullSecrets" $cfCommonTplSemver ) . | nindent 8 }} + serviceAccountName: {{ include "runner.serviceAccountName" . }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + initContainers: + - name: init + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.init.image "context" .) }} + imagePullPolicy: {{ .Values.init.image.pullPolicy | default "IfNotPresent" }} + command: + - /bin/bash + args: + - -ec + - | {{ .Files.Get "files/init-runtime.sh" | nindent 10 }} + env: + {{- include "runner-init.environment-variables" . | nindent 8 }} + {{- with .Values.init.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + containers: + - name: runner + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.image "context" .) }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} + env: + {{- include "runner.environment-variables" . | nindent 8 }} + ports: + - name: http + containerPort: 8080 + readinessProbe: + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + httpGet: + path: /health + port: http + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.sidecar.enabled }} + - name: reconcile-runtime + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.sidecar.image "context" .) }} + imagePullPolicy: {{ .Values.sidecar.image.pullPolicy | default "IfNotPresent" }} + command: + - /bin/bash + args: + - -ec + - | {{ .Files.Get "files/reconcile-runtime.sh" | nindent 10 }} + env: + {{- include "runner-sidecar.environment-variables" . | nindent 8 }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.extraVolumes }} + volumes: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_helpers.tpl b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_helpers.tpl new file mode 100644 index 000000000..2608cb67e --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_helpers.tpl @@ -0,0 +1,42 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "runner.name" -}} + {{- printf "%s-%s" (include "cf-runtime.name" .) "runner" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "runner.fullname" -}} + {{- printf "%s-%s" (include "cf-runtime.fullname" .) "runner" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "runner.labels" -}} +{{ include "cf-runtime.labels" . }} +codefresh.io/application: runner +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "runner.selectorLabels" -}} +{{ include "cf-runtime.selectorLabels" . }} +codefresh.io/application: runner +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "runner.serviceAccountName" -}} + {{- if .Values.serviceAccount.create }} + {{- default (include "runner.fullname" .) .Values.serviceAccount.name }} + {{- else }} + {{- default "default" .Values.serviceAccount.name }} + {{- end }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_rbac.yaml new file mode 100644 index 000000000..d95b958d5 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/_rbac.yaml @@ -0,0 +1,53 @@ +{{- define "runner.resources.rbac" -}} +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "runner.serviceAccountName" . }} + labels: + {{- include "runner.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- +{{- if .Values.rbac.create }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "runner.fullname" . }} + labels: + {{- include "runner.labels" . | nindent 4 }} +rules: + - apiGroups: [ "" ] + resources: [ "pods", "persistentvolumeclaims" ] + verbs: [ "get", "create", "delete", patch ] + - apiGroups: [ "" ] + resources: [ "configmaps", "secrets" ] + verbs: [ "get", "create", "update", patch ] + - apiGroups: [ "apps" ] + resources: [ "deployments" ] + verbs: [ "get" ] +{{- with .Values.rbac.rules }} + {{ toYaml . | nindent 2 }} +{{- end }} +{{- end }} +--- +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "runner.fullname" . }} + labels: + {{- include "runner.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "runner.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ include "runner.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_init-container.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_init-container.yaml new file mode 100644 index 000000000..6dda110f7 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_init-container.yaml @@ -0,0 +1,30 @@ +{{- define "runner-init.environment-variables.defaults" }} +HOME: /tmp +{{- end }} + +{{- define "runner-init.environment-variables.calculated" }} +AGENT_NAME: {{ include "runtime.runtime-environment-spec.agent-name" . }} +API_HOST: {{ include "runtime.runtime-environment-spec.codefresh-host" . }} +AGENT_CODEFRESH_TOKEN: + valueFrom: + secretKeyRef: + name: {{ include "runner.fullname" . }} + key: agent-codefresh-token + optional: true +EXISTING_AGENT_CODEFRESH_TOKEN: {{ include "runtime.agent-token-env-var-value" . | nindent 2 }} +KUBE_CONTEXT: {{ include "runtime.runtime-environment-spec.context-name" . }} +KUBE_NAMESPACE: {{ .Release.Namespace }} +OWNER_NAME: {{ include "runner.fullname" . }} +RUNTIME_NAME: {{ include "runtime.runtime-environment-spec.runtime-name" . }} +SECRET_NAME: {{ include "runner.fullname" . }} +USER_CODEFRESH_TOKEN: {{ include "runtime.installation-token-env-var-value" . | nindent 2 }} +{{- end }} + +{{- define "runner-init.environment-variables" }} + {{- $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} + {{- $defaults := (include "runner-init.environment-variables.defaults" . | fromYaml) }} + {{- $calculated := (include "runner-init.environment-variables.calculated" . | fromYaml) }} + {{- $overrides := .Values.env }} + {{- $mergedValues := mergeOverwrite (merge $defaults $calculated) $overrides }} + {{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $mergedValues "context" .) }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_main-container.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_main-container.yaml new file mode 100644 index 000000000..4d3f0304e --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_main-container.yaml @@ -0,0 +1,28 @@ +{{- define "runner.environment-variables.defaults" }} +AGENT_MODE: InCluster +SELF_DEPLOYMENT_NAME: + valueFrom: + fieldRef: + fieldPath: metadata.name +{{- end }} + +{{- define "runner.environment-variables.calculated" }} +AGENT_ID: {{ include "runtime.runtime-environment-spec.agent-name" . }} +CODEFRESH_HOST: {{ include "runtime.runtime-environment-spec.codefresh-host" . }} +CODEFRESH_IN_CLUSTER_RUNTIME: {{ include "runtime.runtime-environment-spec.runtime-name" . }} +CODEFRESH_TOKEN: + valueFrom: + secretKeyRef: + name: {{ include "runner.fullname" . }} + key: agent-codefresh-token +DOCKER_REGISTRY: {{ .Values.global.imageRegistry }} +{{- end }} + +{{- define "runner.environment-variables" }} +{{- $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{- $defaults := (include "runner.environment-variables.defaults" . | fromYaml) }} +{{- $calculated := (include "runner.environment-variables.calculated" . | fromYaml) }} +{{- $overrides := .Values.env }} +{{- $mergedValues := mergeOverwrite (merge $defaults $calculated) $overrides }} +{{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $mergedValues "context" .) }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_sidecar-container.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_sidecar-container.yaml new file mode 100644 index 000000000..3adcbe5d4 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/runner/environment-variables/_sidecar-container.yaml @@ -0,0 +1,22 @@ +{{- define "runner-sidecar.environment-variables.defaults" }} +HOME: /tmp +{{- end }} + +{{- define "runner-sidecar.environment-variables.calculated" }} +API_HOST: {{ include "runtime.runtime-environment-spec.codefresh-host" . }} +USER_CODEFRESH_TOKEN: {{ include "runtime.installation-token-env-var-value" . | nindent 2 }} +KUBE_CONTEXT: {{ include "runtime.runtime-environment-spec.context-name" . }} +KUBE_NAMESPACE: {{ .Release.Namespace }} +OWNER_NAME: {{ include "runner.fullname" . }} +RUNTIME_NAME: {{ include "runtime.runtime-environment-spec.runtime-name" . }} +CONFIGMAP_NAME: {{ printf "%s-%s" (include "runtime.fullname" .) "spec" }} +{{- end }} + +{{- define "runner-sidecar.environment-variables" }} + {{- $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} + {{- $defaults := (include "runner-sidecar.environment-variables.defaults" . | fromYaml) }} + {{- $calculated := (include "runner-sidecar.environment-variables.calculated" . | fromYaml) }} + {{- $overrides := .Values.sidecar.env }} + {{- $mergedValues := mergeOverwrite (merge $defaults $calculated) $overrides }} + {{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $mergedValues "context" .) }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_cronjob.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_cronjob.yaml new file mode 100644 index 000000000..20bd2d56e --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_cronjob.yaml @@ -0,0 +1,58 @@ +{{- define "dind-volume-provisioner.resources.cronjob" -}} +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{- if not (eq .Values.storage.backend "local") }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "dind-volume-cleanup.fullname" . }} + labels: + {{- include "dind-volume-cleanup.labels" . | nindent 4 }} +spec: + concurrencyPolicy: {{ .Values.concurrencyPolicy }} + schedule: {{ .Values.schedule | quote }} + successfulJobsHistoryLimit: {{ .Values.successfulJobsHistory }} + failedJobsHistoryLimit: {{ .Values.failedJobsHistory }} + {{- with .Values.suspend }} + suspend: {{ . }} + {{- end }} + jobTemplate: + spec: + template: + metadata: + labels: + {{- include "dind-volume-cleanup.selectorLabels" . | nindent 12 }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 12 }} + {{- end }} + spec: + {{- include (printf "%s.image.pullSecrets" $cfCommonTplSemver ) . | nindent 10 }} + serviceAccountName: {{ include "dind-volume-provisioner.serviceAccountName" . }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + restartPolicy: {{ .Values.restartPolicy | default "Never" }} + containers: + - name: dind-volume-cleanup + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.image "context" .) }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "Always" }} + env: + {{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" .Values.env "context" .) | nindent 12 }} + - name: PROVISIONED_BY + value: {{ include "dind-volume-provisioner.volumeProvisionerName" . }} + resources: + {{- toYaml .Values.resources | nindent 14 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_daemonset.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_daemonset.yaml new file mode 100644 index 000000000..cb463231d --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_daemonset.yaml @@ -0,0 +1,98 @@ +{{- define "dind-volume-provisioner.resources.daemonset" -}} +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{ $localVolumeParentDir := .Values.storage.local.volumeParentDir }} +{{- if eq .Values.storage.backend "local" }} +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "dind-lv-monitor.fullname" . }} + labels: + {{- include "dind-lv-monitor.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "dind-lv-monitor.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "dind-lv-monitor.selectorLabels" . | nindent 8 }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- include (printf "%s.image.pullSecrets" $cfCommonTplSemver ) . | nindent 8 }} + serviceAccountName: {{ include "dind-volume-provisioner.serviceAccountName" . }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.volumePermissions.enabled }} + initContainers: + - name: volume-permissions + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.volumePermissions.image "context" .) }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | default "Always" }} + command: + - /bin/sh + args: + - -ec + - | + chown -R {{ .Values.podSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ $localVolumeParentDir }} + volumeMounts: + - mountPath: {{ $localVolumeParentDir }} + name: dind-volume-dir + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 10 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 10 }} + {{- end }} + resources: + {{- toYaml .Values.volumePermissions.resources | nindent 10 }} + {{- end }} + containers: + - name: dind-lv-monitor + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.image "context" .) }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "Always" }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 10 }} + {{- end }} + command: + - /home/dind-volume-utils/bin/local-volumes-agent + env: + {{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" .Values.env "context" .) | nindent 10 }} + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: VOLUME_PARENT_DIR + value: {{ $localVolumeParentDir }} + resources: + {{- toYaml .Values.resources | nindent 10 }} + volumeMounts: + - mountPath: {{ $localVolumeParentDir }} + readOnly: false + name: dind-volume-dir + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + volumes: + - name: dind-volume-dir + hostPath: + path: {{ $localVolumeParentDir }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_deployment.yaml new file mode 100644 index 000000000..9252b4520 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_deployment.yaml @@ -0,0 +1,67 @@ +{{- define "dind-volume-provisioner.resources.deployment" -}} +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "dind-volume-provisioner.fullname" . }} + labels: + {{- include "dind-volume-provisioner.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicasCount }} + strategy: + type: {{ .Values.updateStrategy.type }} + selector: + matchLabels: + {{- include "dind-volume-provisioner.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "dind-volume-provisioner.selectorLabels" . | nindent 8 }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- include (printf "%s.image.pullSecrets" $cfCommonTplSemver ) . | nindent 8 }} + serviceAccountName: {{ include "dind-volume-provisioner.serviceAccountName" . }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + containers: + - name: dind-volume-provisioner + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" .Values.image "context" .) }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "Always" }} + command: + - /usr/local/bin/dind-volume-provisioner + - -v=4 + - --resync-period=50s + env: + {{- include "dind-volume-provisioner.environment-variables" . | nindent 8 }} + ports: + - name: http + containerPort: 8080 + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + {{- include "dind-volume-provisioner.volumeMounts.calculated" . | nindent 8 }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + volumes: + {{- include "dind-volume-provisioner.volumes.calculated" . | nindent 6 }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_env-vars.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_env-vars.yaml new file mode 100644 index 000000000..e1f5dfe60 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_env-vars.yaml @@ -0,0 +1,88 @@ +{{- define "dind-volume-provisioner.environment-variables.defaults" }} +{{- end }} + +{{- define "dind-volume-provisioner.environment-variables.calculated" }} +DOCKER_REGISTRY: {{ .Values.global.imageRegistry }} +PROVISIONER_NAME: {{ include "dind-volume-provisioner.volumeProvisionerName" . }} + +{{- if or .Values.storage.ebs.accessKeyId .Values.storage.ebs.accessKeyIdSecretKeyRef }} +AWS_ACCESS_KEY_ID: + {{- if .Values.storage.ebs.accessKeyId }} + valueFrom: + secretKeyRef: + name: {{ include "dind-volume-provisioner.fullname" . }} + key: aws_access_key_id + {{- else if .Values.storage.ebs.accessKeyIdSecretKeyRef }} + valueFrom: + secretKeyRef: + {{- .Values.storage.ebs.accessKeyIdSecretKeyRef | toYaml | nindent 6 }} + {{- end }} +{{- end }} + +{{- if or .Values.storage.ebs.secretAccessKey .Values.storage.ebs.secretAccessKeySecretKeyRef }} +AWS_SECRET_ACCESS_KEY: + {{- if .Values.storage.ebs.secretAccessKey }} + valueFrom: + secretKeyRef: + name: {{ include "dind-volume-provisioner.fullname" . }} + key: aws_secret_access_key + {{- else if .Values.storage.ebs.secretAccessKeySecretKeyRef }} + valueFrom: + secretKeyRef: + {{- .Values.storage.ebs.secretAccessKeySecretKeyRef | toYaml | nindent 6 }} + {{- end }} +{{- end }} + +{{- if or .Values.storage.gcedisk.serviceAccountJson .Values.storage.gcedisk.serviceAccountJsonSecretKeyRef }} +GOOGLE_APPLICATION_CREDENTIALS: {{ printf "/etc/dind-volume-provisioner/credentials/%s" (.Values.storage.gcedisk.serviceAccountJsonSecretKeyRef.key | default "google-service-account.json") }} +{{- end }} + +{{- if and .Values.storage.mountAzureJson }} +AZURE_CREDENTIAL_FILE: /etc/kubernetes/azure.json +CLOUDCONFIG_AZURE: /etc/kubernetes/azure.json +{{- end }} + +{{- end }} + +{{- define "dind-volume-provisioner.environment-variables" }} +{{- $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{- $defaults := (include "dind-volume-provisioner.environment-variables.defaults" . | fromYaml) }} +{{- $calculated := (include "dind-volume-provisioner.environment-variables.calculated" . | fromYaml) }} +{{- $overrides := .Values.env }} +{{- $mergedValues := mergeOverwrite (merge $defaults $calculated) $overrides }} +{{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $mergedValues "context" .) }} +{{- end }} + + +{{- define "dind-volume-provisioner.volumes.calculated" }} + {{- if .Values.storage.gcedisk.serviceAccountJson }} +- name: credentials + secret: + secretName: {{ include "dind-volume-provisioner.fullname" . }} + optional: true + {{- else if .Values.storage.gcedisk.serviceAccountJsonSecretKeyRef }} +- name: credentials + secret: + secretName: {{ .Values.storage.gcedisk.serviceAccountJsonSecretKeyRef.name }} + optional: true + {{- end }} + {{- if .Values.storage.mountAzureJson }} +- name: azure-json + hostPath: + path: /etc/kubernetes/azure.json + type: File + {{- end }} +{{- end }} + +{{- define "dind-volume-provisioner.volumeMounts.calculated" }} + {{- if or .Values.storage.gcedisk.serviceAccountJson .Values.storage.gcedisk.serviceAccountJsonSecretKeyRef }} +- name: credentials + readOnly: true + mountPath: "/etc/dind-volume-provisioner/credentials" + {{- end }} + {{- if .Values.storage.mountAzureJson }} +- name: azure-json + readOnly: true + mountPath: "/etc/kubernetes/azure.json" + {{- end }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_helpers.tpl b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_helpers.tpl new file mode 100644 index 000000000..e3d3a0d3f --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_helpers.tpl @@ -0,0 +1,93 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "dind-volume-provisioner.name" -}} + {{- printf "%s-%s" (include "cf-runtime.name" .) "volume-provisioner" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "dind-volume-provisioner.fullname" -}} + {{- printf "%s-%s" (include "cf-runtime.fullname" .) "volume-provisioner" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{- define "dind-volume-cleanup.fullname" -}} + {{- printf "%s-%s" (include "cf-runtime.fullname" .) "volume-cleanup" | trunc 52 | trimSuffix "-" }} +{{- end }} + +{{- define "dind-lv-monitor.fullname" -}} + {{- printf "%s-%s" (include "cf-runtime.fullname" .) "lv-monitor" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Provisioner name for storage class +*/}} +{{- define "dind-volume-provisioner.volumeProvisionerName" }} + {{- printf "codefresh.io/dind-volume-provisioner-runner-%s" .Release.Namespace }} +{{- end }} + +{{/* +Common labels for dind-lv-monitor +*/}} +{{- define "dind-lv-monitor.labels" -}} +{{ include "cf-runtime.labels" . }} +codefresh.io/application: lv-monitor +{{- end }} + +{{/* +Selector labels for dind-lv-monitor +*/}} +{{- define "dind-lv-monitor.selectorLabels" -}} +{{ include "cf-runtime.selectorLabels" . }} +codefresh.io/application: lv-monitor +{{- end }} + +{{/* +Common labels for dind-volume-provisioner +*/}} +{{- define "dind-volume-provisioner.labels" -}} +{{ include "cf-runtime.labels" . }} +codefresh.io/application: volume-provisioner +{{- end }} + +{{/* +Selector labels for dind-volume-provisioner +*/}} +{{- define "dind-volume-provisioner.selectorLabels" -}} +{{ include "cf-runtime.selectorLabels" . }} +codefresh.io/application: volume-provisioner +{{- end }} + +{{/* +Common labels for dind-volume-cleanup +*/}} +{{- define "dind-volume-cleanup.labels" -}} +{{ include "cf-runtime.labels" . }} +codefresh.io/application: pv-cleanup +{{- end }} + +{{/* +Common labels for dind-volume-cleanup +*/}} +{{- define "dind-volume-cleanup.selectorLabels" -}} +{{ include "cf-runtime.selectorLabels" . }} +codefresh.io/application: pv-cleanup +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "dind-volume-provisioner.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "dind-volume-provisioner.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{- define "dind-volume-provisioner.storageClassName" }} +{{- printf "dind-local-volumes-runner-%s" .Release.Namespace }} +{{- end }} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_rbac.yaml new file mode 100644 index 000000000..fbcbc684f --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_rbac.yaml @@ -0,0 +1,71 @@ +{{- define "dind-volume-provisioner.resources.rbac" -}} +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "dind-volume-provisioner.serviceAccountName" . }} + labels: + {{- include "dind-volume-provisioner.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- +{{- if .Values.rbac.create }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "dind-volume-provisioner.fullname" . }} + labels: + {{- include "dind-volume-provisioner.labels" . | nindent 4 }} +rules: + - apiGroups: [ "" ] + resources: [ "persistentvolumes" ] + verbs: [ "get", "list", "watch", "create", "delete", "patch" ] + - apiGroups: [ "" ] + resources: [ "persistentvolumeclaims" ] + verbs: [ "get", "list", "watch", "update", "delete" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "storageclasses" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "" ] + resources: [ "events" ] + verbs: [ "list", "watch", "create", "update", "patch" ] + - apiGroups: [ "" ] + resources: [ "secrets" ] + verbs: [ "get", "list" ] + - apiGroups: [ "" ] + resources: [ "nodes" ] + verbs: [ "get", "list", "watch" ] + - apiGroups: [ "" ] + resources: [ "pods" ] + verbs: [ "get", "list", "watch", "create", "delete", "patch" ] + - apiGroups: [ "" ] + resources: [ "endpoints" ] + verbs: [ "get", "list", "watch", "create", "update", "delete" ] + - apiGroups: [ "coordination.k8s.io" ] + resources: [ "leases" ] + verbs: [ "get", "create", "update" ] +{{- with .Values.rbac.rules }} + {{ toYaml . | nindent 2 }} +{{- end }} +{{- end }} +--- +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "dind-volume-provisioner.fullname" . }} + labels: + {{- include "dind-volume-provisioner.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "dind-volume-provisioner.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "dind-volume-provisioner.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_secret.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_secret.yaml new file mode 100644 index 000000000..f361a7991 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_secret.yaml @@ -0,0 +1,22 @@ +{{- define "dind-volume-provisioner.resources.secret" -}} +{{- if or .Values.storage.ebs.accessKeyId .Values.storage.ebs.secretAccessKey .Values.storage.gcedisk.serviceAccountJson }} +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ include "dind-volume-provisioner.fullname" . }} + labels: + {{- include "dind-volume-provisioner.labels" . | nindent 4 }} +stringData: + {{- with .Values.storage.gcedisk.serviceAccountJson }} + google-service-account.json: | +{{- . | nindent 4 }} + {{- end }} + {{- with .Values.storage.ebs.accessKeyId }} + aws_access_key_id: {{ . }} + {{- end }} + {{- with .Values.storage.ebs.secretAccessKey }} + aws_secret_access_key: {{ . }} + {{- end }} +{{- end }} +{{- end -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_storageclass.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_storageclass.yaml new file mode 100644 index 000000000..62e910c87 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_components/volume-provisioner/_storageclass.yaml @@ -0,0 +1,47 @@ +{{- define "dind-volume-provisioner.resources.storageclass" -}} +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + {{/* has to be exactly that */}} + name: {{ include "dind-volume-provisioner.storageClassName" . }} + labels: + {{- include "dind-volume-provisioner.labels" . | nindent 4 }} +provisioner: {{ include "dind-volume-provisioner.volumeProvisionerName" . }} +parameters: +{{- if eq .Values.storage.backend "local" }} + volumeBackend: local + volumeParentDir: {{ .Values.storage.local.volumeParentDir }} +{{- else if eq .Values.storage.backend "gcedisk" }} + volumeBackend: {{ .Values.storage.backend }} + type: {{ .Values.storage.gcedisk.volumeType | default "pd-ssd" }} + zone: {{ required ".Values.storage.gcedisk.availabilityZone is required" .Values.storage.gcedisk.availabilityZone }} + fsType: {{ .Values.storage.fsType | default "ext4" }} +{{- else if or (eq .Values.storage.backend "ebs") (eq .Values.storage.backend "ebs-csi")}} + volumeBackend: {{ .Values.storage.backend }} + VolumeType: {{ .Values.storage.ebs.volumeType | default "gp3" }} + AvailabilityZone: {{ required ".Values.storage.ebs.availabilityZone is required" .Values.storage.ebs.availabilityZone }} + fsType: {{ .Values.storage.fsType | default "ext4" }} + encrypted: {{ .Values.storage.ebs.encrypted | default "false" | quote }} + {{- with .Values.storage.ebs.kmsKeyId }} + kmsKeyId: {{ . | quote }} + {{- end }} + {{- with .Values.storage.ebs.iops }} + iops: {{ . | quote }} + {{- end }} + {{- with .Values.storage.ebs.throughput }} + throughput: {{ . | quote }} + {{- end }} +{{- else if or (eq .Values.storage.backend "azuredisk") (eq .Values.storage.backend "azuredisk-csi")}} + volumeBackend: {{ .Values.storage.backend }} + kind: managed + skuName: {{ .Values.storage.azuredisk.skuName | default "Premium_LRS" }} + fsType: {{ .Values.storage.fsType | default "ext4" }} + cachingMode: {{ .Values.storage.azuredisk.cachingMode | default "None" }} + {{- with .Values.storage.azuredisk.availabilityZone }} + availabilityZone: {{ . | quote }} + {{- end }} + {{- with .Values.storage.azuredisk.resourceGroup }} + resourceGroup: {{ . | quote }} + {{- end }} +{{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/_helpers.tpl b/charts/codefresh/cf-runtime/6.3.58/templates/_helpers.tpl new file mode 100644 index 000000000..72f44e36a --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/_helpers.tpl @@ -0,0 +1,51 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "cf-runtime.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cf-runtime.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cf-runtime.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "cf-runtime.labels" -}} +helm.sh/chart: {{ include "cf-runtime.chart" . }} +{{ include "cf-runtime.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "cf-runtime.selectorLabels" -}} +app.kubernetes.io/name: {{ include "cf-runtime.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/deployment.yaml new file mode 100644 index 000000000..90341b305 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/deployment.yaml @@ -0,0 +1,9 @@ +{{- $appProxyContext := deepCopy . }} +{{- $_ := set $appProxyContext "Values" (get .Values "appProxy") }} +{{- $_ := set $appProxyContext.Values "global" (get .Values "global") }} +{{- $_ := set $appProxyContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $appProxyContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $appProxyContext.Values.enabled }} +{{- include "app-proxy.resources.deployment" $appProxyContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/ingress.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/ingress.yaml new file mode 100644 index 000000000..56ab5e95e --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/ingress.yaml @@ -0,0 +1,9 @@ +{{- $appProxyContext := deepCopy . }} +{{- $_ := set $appProxyContext "Values" (get .Values "appProxy") }} +{{- $_ := set $appProxyContext.Values "global" (get .Values "global") }} +{{- $_ := set $appProxyContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $appProxyContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $appProxyContext.Values.enabled }} +{{- include "app-proxy.resources.ingress" $appProxyContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/rbac.yaml new file mode 100644 index 000000000..4db87dcb4 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/rbac.yaml @@ -0,0 +1,9 @@ +{{- $appProxyContext := deepCopy . }} +{{- $_ := set $appProxyContext "Values" (get .Values "appProxy") }} +{{- $_ := set $appProxyContext.Values "global" (get .Values "global") }} +{{- $_ := set $appProxyContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $appProxyContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $appProxyContext.Values.enabled }} +{{- include "app-proxy.resources.rbac" $appProxyContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/service.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/service.yaml new file mode 100644 index 000000000..0b9d85ec0 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/app-proxy/service.yaml @@ -0,0 +1,9 @@ +{{- $appProxyContext := deepCopy . }} +{{- $_ := set $appProxyContext "Values" (get .Values "appProxy") }} +{{- $_ := set $appProxyContext.Values "global" (get .Values "global") }} +{{- $_ := set $appProxyContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $appProxyContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $appProxyContext.Values.enabled }} +{{- include "app-proxy.resources.service" $appProxyContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/deployment.yaml new file mode 100644 index 000000000..494288240 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/deployment.yaml @@ -0,0 +1,9 @@ +{{- $eventExporterContext := deepCopy . }} +{{- $_ := set $eventExporterContext "Values" (get .Values "event-exporter") }} +{{- $_ := set $eventExporterContext.Values "global" (get .Values "global") }} +{{- $_ := set $eventExporterContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $eventExporterContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if and $eventExporterContext.Values.enabled }} +{{- include "event-exporter.resources.deployment" $eventExporterContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/rbac.yaml new file mode 100644 index 000000000..6a9bf5c65 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/rbac.yaml @@ -0,0 +1,9 @@ +{{- $eventExporterContext := deepCopy . }} +{{- $_ := set $eventExporterContext "Values" (get .Values "event-exporter") }} +{{- $_ := set $eventExporterContext.Values "global" (get .Values "global") }} +{{- $_ := set $eventExporterContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $eventExporterContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if and $eventExporterContext.Values.enabled }} +{{- include "event-exporter.resources.rbac" $eventExporterContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/service.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/service.yaml new file mode 100644 index 000000000..c5d856dfe --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/event-exporter/service.yaml @@ -0,0 +1,11 @@ +{{- $eventExporterContext := deepCopy . }} +{{- $_ := set $eventExporterContext "Values" (get .Values "event-exporter") }} +{{- $_ := set $eventExporterContext.Values "global" (get .Values "global") }} +{{- $_ := set $eventExporterContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $eventExporterContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $eventExporterContext.Values.enabled }} +{{- include "event-exporter.resources.service" $eventExporterContext }} +--- +{{- include "event-exporter.resources.serviceMonitor" $eventExporterContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/extra/extra-resources.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/extra/extra-resources.yaml new file mode 100644 index 000000000..1a9777c64 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/extra/extra-resources.yaml @@ -0,0 +1,6 @@ +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} + +{{- range .Values.extraResources }} +--- +{{ include (printf "%s.tplrender" $cfCommonTplSemver) (dict "Values" . "context" $) }} +{{- end }} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/extra/runtime-images-cm.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/extra/runtime-images-cm.yaml new file mode 100644 index 000000000..f269c84b2 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/extra/runtime-images-cm.yaml @@ -0,0 +1,19 @@ +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{ $values := .Values.runtime.engine.runtimeImages }} +--- +kind: ConfigMap +apiVersion: v1 +metadata: + {{- /* dummy template just to list runtime images */}} + name: {{ include "runtime.fullname" . }}-images + labels: + {{- include "runtime.labels" . | nindent 4 }} + annotations: + {{- with $values.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +data: + images: | + {{- range $key, $val := $values }} + image: {{ $val }} + {{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/cm-update-runtime.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/cm-update-runtime.yaml new file mode 100644 index 000000000..46a306c56 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/cm-update-runtime.yaml @@ -0,0 +1,18 @@ +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{ $values := .Values.runtime.patch }} +{{- if $values.enabled }} +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: {{ include "runtime.fullname" . }}-spec + labels: + {{- include "runtime.labels" . | nindent 4 }} + annotations: + {{- with $values.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +data: + runtime.yaml: | + {{ include "runtime.runtime-environment-spec.template" . | nindent 4 | trim }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/job-gencerts-dind.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/job-gencerts-dind.yaml new file mode 100644 index 000000000..4a08a229c --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/job-gencerts-dind.yaml @@ -0,0 +1,68 @@ +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{ $values := .Values.runtime.gencerts }} +{{- if and $values.enabled }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "runtime.fullname" . }}-gencerts-dind + labels: + {{- include "runtime.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-weight: "3" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + {{- with $values.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with $values.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ . }} + {{- end }} + {{- with $values.backoffLimit }} + backoffLimit: {{ . | int }} + {{- end }} + template: + metadata: + name: {{ include "runtime.fullname" . }}-gencerts-dind + labels: + {{- include "runtime.labels" . | nindent 8 }} + spec: + {{- if $values.rbac.enabled }} + serviceAccountName: {{ template "runtime.fullname" . }}-gencerts-dind + {{- end }} + securityContext: + {{- toYaml $values.podSecurityContext | nindent 8 }} + containers: + - name: gencerts-dind + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" $values.image "context" .) }} + imagePullPolicy: {{ $values.image.pullPolicy | default "Always" }} + command: + - "/bin/bash" + args: + - -ec + - | {{ .Files.Get "files/configure-dind-certs.sh" | nindent 10 }} + env: + - name: NAMESPACE + value: {{ .Release.Namespace }} + - name: RELEASE + value: {{ .Release.Name }} + - name: CF_API_HOST + value: {{ include "runtime.runtime-environment-spec.codefresh-host" . }} + - name: CF_API_TOKEN + {{- include "runtime.installation-token-env-var-value" . | indent 10}} + {{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $values.env "context" .) | nindent 8 }} + {{- with $values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $values.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + restartPolicy: OnFailure +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/job-update-runtime.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/job-update-runtime.yaml new file mode 100644 index 000000000..955e882d7 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/job-update-runtime.yaml @@ -0,0 +1,77 @@ +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{ $values := .Values.runtime.patch }} +{{- if $values.enabled }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "runtime.fullname" . }}-patch + labels: + {{- include "runtime.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-weight: "5" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + {{- with $values.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with $values.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ . }} + {{- end }} + {{- with $values.backoffLimit }} + backoffLimit: {{ . | int }} + {{- end }} + template: + metadata: + name: {{ include "runtime.fullname" . }}-patch + labels: + {{- include "runtime.labels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml $values.podSecurityContext | nindent 8 }} + containers: + - name: patch-runtime + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" $values.image "context" .) }} + imagePullPolicy: {{ $values.image.pullPolicy | default "Always" }} + command: + - "/bin/bash" + args: + - -ec + - | + codefresh auth create-context --api-key $API_KEY --url $API_HOST + cat /usr/share/extras/runtime.yaml + codefresh get re +{{- if .Values.runtime.agent }} + codefresh patch re -f /usr/share/extras/runtime.yaml +{{- else }} + codefresh patch sys-re -f /usr/share/extras/runtime.yaml +{{- end }} + env: + - name: API_KEY + {{- include "runtime.installation-token-env-var-value" . | indent 10}} + - name: API_HOST + value: {{ include "runtime.runtime-environment-spec.codefresh-host" . }} + {{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $values.env "context" .) | nindent 8 }} + volumeMounts: + - name: config + mountPath: /usr/share/extras/runtime.yaml + subPath: runtime.yaml + {{- with $values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $values.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + restartPolicy: OnFailure + volumes: + - name: config + configMap: + name: {{ include "runtime.fullname" . }}-spec +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/rbac-gencerts-dind.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/rbac-gencerts-dind.yaml new file mode 100644 index 000000000..4907dac38 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/post-install/rbac-gencerts-dind.yaml @@ -0,0 +1,37 @@ +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{ $values := .Values.runtime.gencerts }} +{{- if and $values.enabled }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "runtime.fullname" . }}-gencerts-dind + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "runtime.fullname" . }}-gencerts-dind + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "runtime.fullname" . }}-gencerts-dind + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "runtime.fullname" . }}-gencerts-dind +subjects: + - kind: ServiceAccount + name: {{ include "runtime.fullname" . }}-gencerts-dind + namespace: {{ .Release.Namespace }} +{{ end }} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/hooks/pre-delete/job-cleanup-resources.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/pre-delete/job-cleanup-resources.yaml new file mode 100644 index 000000000..0e3c7659f --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/pre-delete/job-cleanup-resources.yaml @@ -0,0 +1,73 @@ +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{ $values := .Values.runtime.patch }} +{{- if and $values.enabled }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "runtime.fullname" . }}-cleanup + labels: + {{- include "runtime.labels" . | nindent 4 }} + annotations: + helm.sh/hook: pre-delete + helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation + {{- with $values.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with $values.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ . }} + {{- end }} + {{- with $values.backoffLimit }} + backoffLimit: {{ . | int }} + {{- end }} + template: + metadata: + name: {{ include "runtime.fullname" . }}-cleanup + labels: + {{- include "runtime.labels" . | nindent 8 }} + spec: + {{- if $values.rbac.enabled }} + serviceAccountName: {{ template "runtime.fullname" . }}-cleanup + {{- end }} + securityContext: + {{- toYaml $values.podSecurityContext | nindent 8 }} + containers: + - name: cleanup + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" $values.image "context" .) }} + imagePullPolicy: {{ $values.image.pullPolicy | default "Always" }} + command: + - "/bin/bash" + args: + - -ec + - | {{ .Files.Get "files/cleanup-runtime.sh" | nindent 10 }} + env: + - name: AGENT_NAME + value: {{ include "runtime.runtime-environment-spec.agent-name" . }} + - name: RUNTIME_NAME + value: {{ include "runtime.runtime-environment-spec.runtime-name" . }} + - name: API_HOST + value: {{ include "runtime.runtime-environment-spec.codefresh-host" . }} + - name: API_TOKEN + {{- include "runtime.installation-token-env-var-value" . | indent 10}} + - name: AGENT + value: {{ .Values.runtime.agent | quote }} + - name: AGENT_SECRET_NAME + value: {{ include "runner.fullname" . }} + - name: DIND_SECRET_NAME + value: codefresh-certs-server + {{- include (printf "%s.env-vars" $cfCommonTplSemver) (dict "Values" $values.env "context" .) | nindent 8 }} + {{- with $values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $values.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + restartPolicy: OnFailure +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/hooks/pre-delete/rbac-cleanup-resources.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/pre-delete/rbac-cleanup-resources.yaml new file mode 100644 index 000000000..468ec2212 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/hooks/pre-delete/rbac-cleanup-resources.yaml @@ -0,0 +1,46 @@ +{{ $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version }} +{{ $values := .Values.runtime.patch }} +{{- if and $values.enabled }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "runtime.fullname" . }}-cleanup + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "runtime.fullname" . }}-cleanup + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed +rules: + - apiGroups: + - "*" + resources: + - "*" + verbs: + - "*" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "runtime.fullname" . }}-cleanup + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "runtime.fullname" . }}-cleanup +subjects: + - kind: ServiceAccount + name: {{ include "runtime.fullname" . }}-cleanup + namespace: {{ .Release.Namespace }} +{{ end }} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/monitor/deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/monitor/deployment.yaml new file mode 100644 index 000000000..00c9fb2f9 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/monitor/deployment.yaml @@ -0,0 +1,9 @@ +{{- $monitorContext := deepCopy . }} +{{- $_ := set $monitorContext "Values" (get .Values "monitor") }} +{{- $_ := set $monitorContext.Values "global" (get .Values "global") }} +{{- $_ := set $monitorContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $monitorContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $monitorContext.Values.enabled }} +{{- include "monitor.resources.deployment" $monitorContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/monitor/rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/monitor/rbac.yaml new file mode 100644 index 000000000..f9812d565 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/monitor/rbac.yaml @@ -0,0 +1,9 @@ +{{- $monitorContext := deepCopy . }} +{{- $_ := set $monitorContext "Values" (get .Values "monitor") }} +{{- $_ := set $monitorContext.Values "global" (get .Values "global") }} +{{- $_ := set $monitorContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $monitorContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $monitorContext.Values.enabled }} +{{- include "monitor.resources.rbac" $monitorContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/monitor/service.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/monitor/service.yaml new file mode 100644 index 000000000..f99706614 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/monitor/service.yaml @@ -0,0 +1,9 @@ +{{- $monitorContext := deepCopy . }} +{{- $_ := set $monitorContext "Values" (get .Values "monitor") }} +{{- $_ := set $monitorContext.Values "global" (get .Values "global") }} +{{- $_ := set $monitorContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $monitorContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $monitorContext.Values.enabled }} +{{- include "monitor.resources.service" $monitorContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/other/external-secrets.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/other/external-secrets.yaml new file mode 100644 index 000000000..dc24e24e5 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/other/external-secrets.yaml @@ -0,0 +1,2 @@ +{{ $templateName := printf "cf-common-%s.external-secrets" (index .Subcharts "cf-common").Chart.Version }} +{{- include $templateName . -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/other/podMonitor.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/other/podMonitor.yaml new file mode 100644 index 000000000..4319b722b --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/other/podMonitor.yaml @@ -0,0 +1,2 @@ +{{ $templateName := printf "cf-common-%s.podMonitor" (index .Subcharts "cf-common").Chart.Version }} +{{- include $templateName . -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/other/serviceMonitor.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/other/serviceMonitor.yaml new file mode 100644 index 000000000..29f890fe2 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/other/serviceMonitor.yaml @@ -0,0 +1,2 @@ +{{ $templateName := printf "cf-common-%s.serviceMonitor" (index .Subcharts "cf-common").Chart.Version }} +{{- include $templateName . -}} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/runner/deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/runner/deployment.yaml new file mode 100644 index 000000000..85777c487 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/runner/deployment.yaml @@ -0,0 +1,9 @@ +{{- $runnerContext := deepCopy . }} +{{- $_ := set $runnerContext "Values" (get .Values "runner") }} +{{- $_ := set $runnerContext.Values "global" (get .Values "global") }} +{{- $_ := set $runnerContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $runnerContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if and $runnerContext.Values.enabled .Values.runtime.agent }} +{{- include "runner.resources.deployment" $runnerContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/runner/rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/runner/rbac.yaml new file mode 100644 index 000000000..d5f8c1323 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/runner/rbac.yaml @@ -0,0 +1,9 @@ +{{- $runnerContext := deepCopy . }} +{{- $_ := set $runnerContext "Values" (get .Values "runner") }} +{{- $_ := set $runnerContext.Values "global" (get .Values "global") }} +{{- $_ := set $runnerContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $runnerContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if and $runnerContext.Values.enabled .Values.runtime.agent }} +{{- include "runner.resources.rbac" $runnerContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/runtime/_helpers.tpl b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/_helpers.tpl new file mode 100644 index 000000000..6ba04fcc3 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/_helpers.tpl @@ -0,0 +1,123 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "runtime.name" -}} + {{- printf "%s" (include "cf-runtime.name" .) | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "runtime.fullname" -}} + {{- printf "%s" (include "cf-runtime.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "runtime.labels" -}} +{{ include "cf-runtime.labels" . }} +codefresh.io/application: runtime +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "runtime.selectorLabels" -}} +{{ include "cf-runtime.selectorLabels" . }} +codefresh.io/application: runtime +{{- end }} + +{{/* +Return runtime image (classic runtime) with private registry prefix +*/}} +{{- define "runtime.runtimeImageName" -}} + {{- if .registry -}} + {{- $imageName := (trimPrefix "quay.io/" .imageFullName) -}} + {{- printf "%s/%s" .registry $imageName -}} + {{- else -}} + {{- printf "%s" .imageFullName -}} + {{- end -}} +{{- end -}} + +{{/* +Environment variable value of Codefresh installation token +*/}} +{{- define "runtime.installation-token-env-var-value" -}} + {{- if .Values.global.codefreshToken }} +valueFrom: + secretKeyRef: + name: {{ include "runtime.installation-token-secret-name" . }} + key: codefresh-api-token + {{- else if .Values.global.codefreshTokenSecretKeyRef }} +valueFrom: + secretKeyRef: + {{- .Values.global.codefreshTokenSecretKeyRef | toYaml | nindent 4 }} + {{- end }} +{{- end }} + +{{/* +Environment variable value of Codefresh agent token +*/}} +{{- define "runtime.agent-token-env-var-value" -}} + {{- if .Values.global.agentToken }} +{{- printf "%s" .Values.global.agentToken | toYaml }} + {{- else if .Values.global.agentTokenSecretKeyRef }} +valueFrom: + secretKeyRef: + {{- .Values.global.agentTokenSecretKeyRef | toYaml | nindent 4 }} + {{- end }} +{{- end }} + +{{/* +Print Codefresh API token secret name +*/}} +{{- define "runtime.installation-token-secret-name" }} +{{- print "codefresh-user-token" }} +{{- end }} + +{{/* +Print Codefresh host +*/}} +{{- define "runtime.runtime-environment-spec.codefresh-host" }} +{{- if and (not .Values.global.codefreshHost) }} + {{- fail "ERROR: .global.codefreshHost is required" }} +{{- else }} + {{- printf "%s" (trimSuffix "/" .Values.global.codefreshHost) }} +{{- end }} +{{- end }} + +{{/* +Print runtime-environment name +*/}} +{{- define "runtime.runtime-environment-spec.runtime-name" }} +{{- if and (not .Values.global.runtimeName) }} + {{- printf "%s/%s" .Values.global.context .Release.Namespace }} +{{- else }} + {{- printf "%s" .Values.global.runtimeName }} +{{- end }} +{{- end }} + +{{/* +Print agent name +*/}} +{{- define "runtime.runtime-environment-spec.agent-name" }} +{{- if and (not .Values.global.agentName) }} + {{- printf "%s_%s" .Values.global.context .Release.Namespace }} +{{- else }} + {{- printf "%s" .Values.global.agentName }} +{{- end }} +{{- end }} + +{{/* +Print context +*/}} +{{- define "runtime.runtime-environment-spec.context-name" }} +{{- if and (not .Values.global.context) }} + {{- fail "ERROR: .global.context is required" }} +{{- else }} + {{- printf "%s" .Values.global.context }} +{{- end }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/runtime/cm-dind-daemon.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/cm-dind-daemon.yaml new file mode 100644 index 000000000..fc7f92905 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/cm-dind-daemon.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + {{- /* has to be a constant */}} + name: codefresh-dind-config + labels: + {{- include "runtime.labels" . | nindent 4 }} +data: + daemon.json: | +{{ coalesce .Values.re.dindDaemon .Values.runtime.dindDaemon | toPrettyJson | indent 4 }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/runtime/rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/rbac.yaml new file mode 100644 index 000000000..a51b12526 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/rbac.yaml @@ -0,0 +1,48 @@ +{{ $values := .Values.runtime }} +--- +{{- if or $values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- /* has to be a constant */}} + name: codefresh-engine + labels: + {{- include "runtime.labels" . | nindent 4 }} + {{- with $values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- +{{- if $values.rbac.create }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: codefresh-engine + labels: + {{- include "runner.labels" . | nindent 4 }} +rules: + - apiGroups: [ "" ] + resources: [ "secrets" ] + verbs: [ "get" ] +{{- with $values.rbac.rules }} + {{ toYaml . | nindent 2 }} +{{- end }} +{{- end }} +--- +{{- if and $values.serviceAccount.create $values.rbac.create }} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: codefresh-engine + labels: + {{- include "runner.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: codefresh-engine +roleRef: + kind: Role + name: codefresh-engine + apiGroup: rbac.authorization.k8s.io +{{- end }} + diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/runtime/runtime-env-spec-tmpl.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/runtime-env-spec-tmpl.yaml new file mode 100644 index 000000000..c0ae0ff82 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/runtime-env-spec-tmpl.yaml @@ -0,0 +1,211 @@ +{{- define "runtime.runtime-environment-spec.template" }} +{{- $cfCommonTplSemver := printf "cf-common-%s" (index .Subcharts "cf-common").Chart.Version -}} +{{- $kubeconfigFilePath := (include "runtime.runtime-environment-spec.runtime-name" .) -}} +{{- $name := (include "runtime.runtime-environment-spec.runtime-name" .) -}} +{{- $engineContext := .Values.runtime.engine -}} +{{- $dindContext := .Values.runtime.dind -}} +{{- $imageRegistry := .Values.global.imageRegistry -}} +metadata: + name: {{ include "runtime.runtime-environment-spec.runtime-name" . }} + agent: {{ .Values.runtime.agent }} +runtimeScheduler: + type: KubernetesPod + {{- if $engineContext.image }} + image: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" $engineContext.image "context" .) | squote }} + {{- end }} + imagePullPolicy: {{ $engineContext.image.pullPolicy }} + {{- with $engineContext.command }} + command: {{- toYaml . | nindent 4 }} + {{- end }} + envVars: + {{- with $engineContext.env }} + {{- range $key, $val := . }} + {{- if or (kindIs "bool" $val) (kindIs "int" $val) (kindIs "float64" $val) }} + {{ $key }}: {{ $val | squote }} + {{- else }} + {{ $key }}: {{ $val }} + {{- end }} + {{- end }} + {{- end }} + COMPOSE_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.COMPOSE_IMAGE) | squote }} + CONTAINER_LOGGER_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.CONTAINER_LOGGER_IMAGE) | squote }} + DOCKER_BUILDER_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.DOCKER_BUILDER_IMAGE) | squote }} + DOCKER_PULLER_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.DOCKER_PULLER_IMAGE) | squote }} + DOCKER_PUSHER_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.DOCKER_PUSHER_IMAGE) | squote }} + DOCKER_TAG_PUSHER_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.DOCKER_TAG_PUSHER_IMAGE) | squote }} + FS_OPS_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.FS_OPS_IMAGE) | squote }} + GIT_CLONE_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.GIT_CLONE_IMAGE) | squote }} + KUBE_DEPLOY: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.KUBE_DEPLOY) | squote }} + PIPELINE_DEBUGGER_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.PIPELINE_DEBUGGER_IMAGE) | squote }} + TEMPLATE_ENGINE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.TEMPLATE_ENGINE) | squote }} + CR_6177_FIXER: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.CR_6177_FIXER) | squote }} + GC_BUILDER_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.GC_BUILDER_IMAGE) | squote }} + COSIGN_IMAGE_SIGNER_IMAGE: {{ include "runtime.runtimeImageName" (dict "registry" $imageRegistry "imageFullName" $engineContext.runtimeImages.COSIGN_IMAGE_SIGNER_IMAGE) | squote }} + {{- with $engineContext.userEnvVars }} + userEnvVars: {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $engineContext.workflowLimits }} + workflowLimits: {{- toYaml . | nindent 4 }} + {{- end }} + cluster: + namespace: {{ .Release.Namespace }} + serviceAccount: {{ $engineContext.serviceAccount }} + {{- if .Values.runtime.agent }} + clusterProvider: + accountId: {{ .Values.global.accountId }} + selector: {{ include "runtime.runtime-environment-spec.context-name" . }} + {{- else }} + {{- if .Values.runtime.inCluster }} + inCluster: true + kubeconfigFilePath: null + {{- else }} + name: {{ $name }} + kubeconfigFilePath: {{ printf "/etc/kubeconfig/%s" $kubeconfigFilePath }} + {{- end }} + {{- end }} + {{- with $engineContext.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with $engineContext.affinity }} + affinity: {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $engineContext.tolerations }} + tolerations: {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $engineContext.podAnnotations }} + annotations: + {{- range $key, $val := . }} + {{ $key }}: {{ $val | squote }} + {{- end }} + {{- end }} + {{- with $engineContext.podLabels }} + labels: {{- toYaml . | nindent 4 }} + {{- end }} + {{- if $engineContext.schedulerName }} + schedulerName: {{ $engineContext.schedulerName }} + {{- end }} + resources: + {{- if $engineContext.resources}} + {{- toYaml $engineContext.resources | nindent 4 }} + {{- end }} +dockerDaemonScheduler: + type: DindKubernetesPod + {{- if $dindContext.image }} + dindImage: {{ include (printf "%s.image.name" $cfCommonTplSemver ) (dict "image" $dindContext.image "context" .) | squote }} + {{- end }} + imagePullPolicy: {{ $dindContext.image.pullPolicy }} + {{- with $dindContext.userAccess }} + userAccess: {{ . }} + {{- end }} + {{- with $dindContext.env }} + envVars: + {{- range $key, $val := . }} + {{- if or (kindIs "bool" $val) (kindIs "int" $val) (kindIs "float64" $val) }} + {{ $key }}: {{ $val | squote }} + {{- else }} + {{ $key }}: {{ $val }} + {{- end }} + {{- end }} + {{- end }} + cluster: + namespace: {{ .Release.Namespace }} + serviceAccount: {{ $dindContext.serviceAccount }} + {{- if .Values.runtime.agent }} + clusterProvider: + accountId: {{ .Values.global.accountId }} + selector: {{ include "runtime.runtime-environment-spec.context-name" . }} + {{- else }} + {{- if .Values.runtime.inCluster }} + inCluster: true + kubeconfigFilePath: null + {{- else }} + name: {{ $name }} + kubeconfigFilePath: {{ printf "/etc/kubeconfig/%s" $kubeconfigFilePath }} + {{- end }} + {{- end }} + {{- with $dindContext.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with $dindContext.affinity }} + affinity: {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $dindContext.tolerations }} + tolerations: {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $dindContext.podAnnotations }} + annotations: + {{- range $key, $val := . }} + {{ $key }}: {{ $val | squote }} + {{- end }} + {{- end }} + {{- with $dindContext.podLabels }} + labels: {{- toYaml . | nindent 4 }} + {{- end }} + {{- if $dindContext.schedulerName }} + schedulerName: {{ $dindContext.schedulerName }} + {{- end }} + {{- if $dindContext.pvcs }} + pvcs: + {{- range $index, $pvc := $dindContext.pvcs }} + - name: {{ $pvc.name }} + reuseVolumeSelector: {{ $pvc.reuseVolumeSelector | squote }} + reuseVolumeSortOrder: {{ $pvc.reuseVolumeSortOrder }} + storageClassName: {{ include (printf "%v.tplrender" $cfCommonTplSemver) (dict "Values" $pvc.storageClassName "context" $) }} + volumeSize: {{ $pvc.volumeSize }} + {{- with $pvc.annotations }} + annotations: {{ . | toYaml | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + defaultDindResources: + {{- with $dindContext.resources }} + {{- if not .requests }} + limits: {{- toYaml .limits | nindent 6 }} + requests: null + {{- else }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} + {{- with $dindContext.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ . }} + {{- end }} + {{- with $dindContext.userVolumeMounts }} + userVolumeMounts: {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $dindContext.userVolumes }} + userVolumes: {{- toYaml . | nindent 4 }} + {{- end }} + {{- if and (not .Values.runtime.agent) }} + clientCertPath: /etc/ssl/cf/ + volumeMounts: + codefresh-certs-server: + name: codefresh-certs-server + mountPath: /etc/ssl/cf + readOnly: false + volumes: + codefresh-certs-server: + name: codefresh-certs-server + secret: + secretName: codefresh-certs-server + {{- end }} +extends: {{- toYaml .Values.runtime.runtimeExtends | nindent 2 }} + {{- if .Values.runtime.description }} +description: {{ .Values.runtime.description }} + {{- else }} +description: null + {{- end }} +{{- if .Values.global.accountId }} +accountId: {{ .Values.global.accountId }} +{{- end }} +{{- if not .Values.runtime.agent }} +accounts: {{- toYaml .Values.runtime.accounts | nindent 2 }} +{{- end }} +{{- if .Values.appProxy.enabled }} +appProxy: + externalIP: >- + {{ printf "https://%s%s" .Values.appProxy.ingress.host (.Values.appProxy.ingress.pathPrefix | default "/") }} +{{- end }} +{{- if not .Values.runtime.agent }} +systemHybrid: true +{{- end }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/runtime/secret.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/secret.yaml new file mode 100644 index 000000000..2366d3ccf --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/secret.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.global.codefreshToken }} +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ include "runtime.installation-token-secret-name" . }} + labels: + {{- include "runtime.labels" . | nindent 4 }} +stringData: + codefresh-api-token: {{ .Values.global.codefreshToken }} +{{- end }} \ No newline at end of file diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/runtime/svc-dind.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/svc-dind.yaml new file mode 100644 index 000000000..098edb4e8 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/runtime/svc-dind.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "runtime.labels" . | nindent 4 }} + app: dind + {{/* has to be a constant */}} + name: dind +spec: + ports: + - name: "dind-port" + port: 1300 + protocol: TCP + clusterIP: None + selector: + app: dind diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/cronjob.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/cronjob.yaml new file mode 100644 index 000000000..db955bc77 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/cronjob.yaml @@ -0,0 +1,11 @@ +{{- $volumeProvisionerContext := deepCopy . }} +{{- $_ := set $volumeProvisionerContext "Values" (get .Values.volumeProvisioner "dind-volume-cleanup") }} +{{- $_ := set $volumeProvisionerContext.Values "serviceAccount" (get .Values.volumeProvisioner "serviceAccount") }} +{{- $_ := set $volumeProvisionerContext.Values "global" (get .Values "global") }} +{{- $_ := set $volumeProvisionerContext.Values "storage" (get .Values "storage") }} +{{- $_ := set $volumeProvisionerContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $volumeProvisionerContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if and $volumeProvisionerContext.Values.enabled .Values.volumeProvisioner.enabled }} +{{- include "dind-volume-provisioner.resources.cronjob" $volumeProvisionerContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/daemonset.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/daemonset.yaml new file mode 100644 index 000000000..39927149e --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/daemonset.yaml @@ -0,0 +1,11 @@ +{{- $volumeProvisionerContext := deepCopy . }} +{{- $_ := set $volumeProvisionerContext "Values" (get .Values.volumeProvisioner "dind-lv-monitor") }} +{{- $_ := set $volumeProvisionerContext.Values "serviceAccount" (get .Values.volumeProvisioner "serviceAccount") }} +{{- $_ := set $volumeProvisionerContext.Values "global" (get .Values "global") }} +{{- $_ := set $volumeProvisionerContext.Values "storage" (get .Values "storage") }} +{{- $_ := set $volumeProvisionerContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $volumeProvisionerContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if and $volumeProvisionerContext.Values.enabled .Values.volumeProvisioner.enabled }} +{{- include "dind-volume-provisioner.resources.daemonset" $volumeProvisionerContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/deployment.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/deployment.yaml new file mode 100644 index 000000000..522fa8791 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/deployment.yaml @@ -0,0 +1,10 @@ +{{- $volumeProvisionerContext := deepCopy . }} +{{- $_ := set $volumeProvisionerContext "Values" (get .Values "volumeProvisioner") }} +{{- $_ := set $volumeProvisionerContext.Values "global" (get .Values "global") }} +{{- $_ := set $volumeProvisionerContext.Values "storage" (get .Values "storage") }} +{{- $_ := set $volumeProvisionerContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $volumeProvisionerContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $volumeProvisionerContext.Values.enabled }} +{{- include "dind-volume-provisioner.resources.deployment" $volumeProvisionerContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/rbac.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/rbac.yaml new file mode 100644 index 000000000..f3ae9609f --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/rbac.yaml @@ -0,0 +1,9 @@ +{{- $volumeProvisionerContext := deepCopy . }} +{{- $_ := set $volumeProvisionerContext "Values" (get .Values "volumeProvisioner") }} +{{- $_ := set $volumeProvisionerContext.Values "global" (get .Values "global") }} +{{- $_ := set $volumeProvisionerContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $volumeProvisionerContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $volumeProvisionerContext.Values.enabled }} +{{- include "dind-volume-provisioner.resources.rbac" $volumeProvisionerContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/secret.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/secret.yaml new file mode 100644 index 000000000..accf601d1 --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/secret.yaml @@ -0,0 +1,10 @@ +{{- $volumeProvisionerContext := deepCopy . }} +{{- $_ := set $volumeProvisionerContext "Values" (get .Values "volumeProvisioner") }} +{{- $_ := set $volumeProvisionerContext.Values "global" (get .Values "global") }} +{{- $_ := set $volumeProvisionerContext.Values "storage" (get .Values "storage") }} +{{- $_ := set $volumeProvisionerContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $volumeProvisionerContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $volumeProvisionerContext.Values.enabled }} +{{- include "dind-volume-provisioner.resources.secret" $volumeProvisionerContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/storageclass.yaml b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/storageclass.yaml new file mode 100644 index 000000000..77a7602da --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/templates/volume-provisioner/storageclass.yaml @@ -0,0 +1,10 @@ +{{- $volumeProvisionerContext := deepCopy . }} +{{- $_ := set $volumeProvisionerContext "Values" (get .Values "volumeProvisioner") }} +{{- $_ := set $volumeProvisionerContext.Values "global" (get .Values "global") }} +{{- $_ := set $volumeProvisionerContext.Values "storage" (get .Values "storage") }} +{{- $_ := set $volumeProvisionerContext.Values "nameOverride" (get .Values "nameOverride") }} +{{- $_ := set $volumeProvisionerContext.Values "fullnameOverride" (get .Values "fullnameOverride") }} + +{{- if $volumeProvisionerContext.Values.enabled }} +{{- include "dind-volume-provisioner.resources.storageclass" $volumeProvisionerContext }} +{{- end }} diff --git a/charts/codefresh/cf-runtime/6.3.58/values.yaml b/charts/codefresh/cf-runtime/6.3.58/values.yaml new file mode 100644 index 000000000..7bb8edc4c --- /dev/null +++ b/charts/codefresh/cf-runtime/6.3.58/values.yaml @@ -0,0 +1,947 @@ +# -- String to partially override cf-runtime.fullname template (will maintain the release name) +nameOverride: "" +# -- String to fully override cf-runtime.fullname template +fullnameOverride: "" + +# -- Global parameters +# @default -- See below +global: + # -- Global Docker image registry + imageRegistry: "" + # -- Global Docker registry secret names as array + imagePullSecrets: [] + + # -- URL of Codefresh Platform (required!) + codefreshHost: "https://g.codefresh.io" + # -- User token in plain text (required if `global.codefreshTokenSecretKeyRef` is omitted!) + # Ref: https://g.codefresh.io/user/settings (see API Keys) + # Minimal API key scopes: Runner-Installation(read+write), Agent(read+write), Agents(read+write) + codefreshToken: "" + # -- User token that references an existing secret containing API key (required if `global.codefreshToken` is omitted!) + codefreshTokenSecretKeyRef: {} + + # E.g. + # codefreshTokenSecretKeyRef: + # name: my-codefresh-api-token + # key: codefresh-api-token + + # -- Account ID (required!) + # Can be obtained here https://g.codefresh.io/2.0/account-settings/account-information + accountId: "" + + # -- K8s context name (required!) + context: "" + # E.g. + # context: prod-ue1-runtime-1 + + # -- Agent Name (optional!) + # If omitted, the following format will be used `{{ .Values.global.context }}_{{ .Release.Namespace }}` + agentName: "" + # E.g. + # agentName: prod-ue1-runtime-1 + + # -- Runtime name (optional!) + # If omitted, the following format will be used `{{ .Values.global.context }}/{{ .Release.Namespace }}` + runtimeName: "" + # E.g. + # runtimeName: prod-ue1-runtime-1/namespace + + # -- DEPRECATED Agent token in plain text. + # !!! MUST BE provided if migrating from < 6.x chart version + agentToken: "" + # -- DEPRECATED Agent token that references an existing secret containing API key. + # !!! MUST BE provided if migrating from < 6.x chart version + agentTokenSecretKeyRef: {} + # E.g. + # agentTokenSecretKeyRef: + # name: my-codefresh-agent-secret + # key: codefresh-agent-token + +# DEPRECATED -- Use `.Values.global.imageRegistry` instead +dockerRegistry: "" + +# DEPRECATED -- Use `.Values.runtime` instead +re: {} + +# -- Runner parameters +# @default -- See below +runner: + # -- Enable the runner + enabled: true + # -- Set number of pods + replicasCount: 1 + # -- Upgrade strategy + updateStrategy: + type: RollingUpdate + # -- Set pod annotations + podAnnotations: {} + + # -- Set image + image: + registry: quay.io + repository: codefresh/venona + tag: 1.10.2 + + # -- Init container + init: + image: + registry: quay.io + repository: codefresh/cli + tag: 0.85.0-rootless + + resources: + limits: + memory: 512Mi + cpu: '1' + requests: + memory: 256Mi + cpu: '0.2' + + # -- Sidecar container + # Reconciles runtime spec from Codefresh API for drift detection + sidecar: + enabled: false + image: + registry: quay.io + repository: codefresh/codefresh-shell + tag: 0.0.2 + env: + RECONCILE_INTERVAL: 300 + resources: {} + + # -- Add additional env vars + env: {} + # E.g. + # env: + # WORKFLOW_CONCURRENCY: 50 # The number of workflow creation and termination tasks the Runner can handle in parallel. Defaults to 50 + + # -- Service Account parameters + serviceAccount: + # -- Create service account + create: true + # -- Override service account name + name: "" + # -- Additional service account annotations + annotations: {} + + # -- RBAC parameters + rbac: + # -- Create RBAC resources + create: true + # -- Add custom rule to the role + rules: [] + + # -- Set security context for the pod + # @default -- See below + podSecurityContext: + enabled: true + runAsUser: 10001 + runAsGroup: 10001 + fsGroup: 10001 + + # -- Readiness probe configuration + # @default -- See below + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + + # -- Set requests and limits + resources: {} + # -- Set node selector + nodeSelector: {} + # -- Set tolerations + tolerations: [] + # -- Set affinity + affinity: {} + +# -- Volume Provisioner parameters +# @default -- See below +volumeProvisioner: + # -- Enable volume-provisioner + enabled: true + # -- Set number of pods + replicasCount: 1 + # -- Upgrade strategy + updateStrategy: + type: Recreate + # -- Set pod annotations + podAnnotations: {} + + # -- Set image + image: + registry: quay.io + repository: codefresh/dind-volume-provisioner + tag: 1.35.0 + # -- Add additional env vars + env: {} + # E.g. + # env: + # THREADINESS: 4 # The number of PVC requests the dind-volume-provisioner can process in parallel. Defaults to 4 + + # -- Service Account parameters + serviceAccount: + # -- Create service account + create: true + # -- Override service account name + name: "" + # -- Additional service account annotations + annotations: {} + # E.g. + # serviceAccount: + # annotations: + # eks.amazonaws.com/role-arn: "arn:aws:iam:::role/" + + # -- RBAC parameters + rbac: + # -- Create RBAC resources + create: true + # -- Add custom rule to the role + rules: [] + + # -- Set security context for the pod + # @default -- See below + podSecurityContext: + enabled: true + runAsUser: 3000 + runAsGroup: 3000 + fsGroup: 3000 + + # -- Set node selector + nodeSelector: {} + # -- Set resources + resources: {} + # -- Set tolerations + tolerations: [] + # -- Set affinity + affinity: {} + + # -- `dind-lv-monitor` DaemonSet parameters + # (local volumes cleaner) + # @default -- See below + dind-lv-monitor: + enabled: true + image: + registry: quay.io + repository: codefresh/dind-volume-utils + tag: 1.29.4 + podAnnotations: {} + podSecurityContext: + enabled: true + runAsUser: 1000 + fsGroup: 1000 + containerSecurityContext: {} + env: {} + resources: {} + nodeSelector: {} + tolerations: + - key: 'codefresh/dind' + operator: 'Exists' + effect: 'NoSchedule' + volumePermissions: + enabled: true + image: + registry: docker.io + repository: alpine + tag: 3.18 + resources: {} + securityContext: + runAsUser: 0 # auto + + # `dind-volume-cleanup` CronJob parameters + # (external volumes cleaner) + # @default -- See below + dind-volume-cleanup: + enabled: true + image: + registry: quay.io + repository: codefresh/dind-volume-cleanup + tag: 1.2.0 + env: {} + concurrencyPolicy: Forbid + schedule: "*/10 * * * *" + successfulJobsHistory: 3 + failedJobsHistory: 1 + suspend: false + podAnnotations: {} + podSecurityContext: + enabled: true + fsGroup: 3000 + runAsGroup: 3000 + runAsUser: 3000 + nodeSelector: {} + affinity: {} + tolerations: [] + +# Storage parameters for volume-provisioner +# @default -- See below +storage: + # -- Set backend volume type (`local`/`ebs`/`ebs-csi`/`gcedisk`/`azuredisk`) + backend: local + # -- Set filesystem type (`ext4`/`xfs`) + fsType: "ext4" + + # Storage parametrs example for local volumes on the K8S nodes filesystem (i.e. `storage.backend=local`) + # https://kubernetes.io/docs/concepts/storage/volumes/#local + # @default -- See below + local: + # -- Set volume path on the host filesystem + volumeParentDir: /var/lib/codefresh/dind-volumes + + # Storage parameters example for aws ebs disks (i.e. `storage.backend=ebs`/`storage.backend=ebs-csi`) + # https://aws.amazon.com/ebs/ + # https://codefresh.io/docs/docs/installation/codefresh-runner/#aws-backend-volume-configuration + # @default -- See below + ebs: + # -- Set EBS volume type (`gp2`/`gp3`/`io1`) (required) + volumeType: "gp2" + # -- Set EBS volumes availability zone (required) + availabilityZone: "us-east-1a" + # -- Enable encryption (optional) + encrypted: "false" + # -- Set KMS encryption key ID (optional) + kmsKeyId: "" + + # -- Set AWS_ACCESS_KEY_ID for volume-provisioner (optional) + # Ref: https://codefresh.io/docs/docs/installation/codefresh-runner/#dind-volume-provisioner-permissions + accessKeyId: "" + # -- Existing secret containing AWS_ACCESS_KEY_ID. + accessKeyIdSecretKeyRef: {} + # E.g. + # accessKeyIdSecretKeyRef: + # name: + # key: + + # -- Set AWS_SECRET_ACCESS_KEY for volume-provisioner (optional) + # Ref: https://codefresh.io/docs/docs/installation/codefresh-runner/#dind-volume-provisioner-permissions + secretAccessKey: "" + # -- Existing secret containing AWS_SECRET_ACCESS_KEY + secretAccessKeySecretKeyRef: {} + # E.g. + # secretAccessKeySecretKeyRef: + # name: + # key: + + # E.g. + # ebs: + # volumeType: gp3 + # availabilityZone: us-east-1c + # encrypted: false + # iops: "5000" + # # I/O operations per second. Only effetive when gp3 volume type is specified. + # # Default value - 3000. + # # Max - 16,000 + # throughput: "500" + # # Throughput in MiB/s. Only effective when gp3 volume type is specified. + # # Default value - 125. + # # Max - 1000. + # ebs: + # volumeType: gp2 + # availabilityZone: us-east-1c + # encrypted: true + # kmsKeyId: "1234abcd-12ab-34cd-56ef-1234567890ab" + # accessKeyId: "MYKEYID" + # secretAccessKey: "MYACCESSKEY" + + # Storage parameters example for gce disks + # https://cloud.google.com/compute/docs/disks#pdspecs + # https://codefresh.io/docs/docs/installation/codefresh-runner/#gke-google-kubernetes-engine-backend-volume-configuration + # @default -- See below + gcedisk: + # -- Set GCP volume backend type (`pd-ssd`/`pd-standard`) + volumeType: "pd-ssd" + # -- Set GCP volume availability zone + availabilityZone: "us-west1-a" + # -- Set Google SA JSON key for volume-provisioner (optional) + serviceAccountJson: "" + # -- Existing secret containing containing Google SA JSON key for volume-provisioner (optional) + serviceAccountJsonSecretKeyRef: {} + # E.g. + # gcedisk: + # volumeType: pd-ssd + # availabilityZone: us-central1-c + # serviceAccountJson: |- + # { + # "type": "service_account", + # "project_id": "...", + # "private_key_id": "...", + # "private_key": "...", + # "client_email": "...", + # "client_id": "...", + # "auth_uri": "...", + # "token_uri": "...", + # "auth_provider_x509_cert_url": "...", + # "client_x509_cert_url": "..." + # } + + # Storage parameters example for Azure Disks + # https://codefresh.io/docs/docs/installation/codefresh-runner/#install-codefresh-runner-on-azure-kubernetes-service-aks + # @default -- See below + azuredisk: + # -- Set storage type (`Premium_LRS`) + skuName: Premium_LRS + cachingMode: None + # availabilityZone: northeurope-1 + # resourceGroup: + # DiskIOPSReadWrite: 500 + # DiskMBpsReadWrite: 100 + + mountAzureJson: false + +# -- Set runtime parameters +# @default -- See below + +runtime: + # -- Set annotation on engine Service Account + # Ref: https://codefresh.io/docs/docs/administration/codefresh-runner/#injecting-aws-arn-roles-into-the-cluster + serviceAccount: + create: true + annotations: {} + # E.g. + # serviceAccount: + # annotations: + # eks.amazonaws.com/role-arn: "arn:aws:iam:::role/" + + # -- Set parent runtime to inherit. + # Should not be changes. Parent runtime is controlled from Codefresh side. + runtimeExtends: + - system/default/hybrid/k8s_low_limits + # -- Runtime description + description: "" + + # -- RBAC parameters + rbac: + # -- Create RBAC resources + create: true + # -- Add custom rule to the engine role + rules: [] + + # -- (for On-Premise only) Enable agent + agent: true + # -- (for On-Premise only) Set inCluster runtime + inCluster: true + # -- (for On-Premise only) Assign accounts to runtime (list of account ids) + accounts: [] + + # -- Parameters for DinD (docker-in-docker) pod (aka "runtime" pod). + dind: + # -- Set dind image. + image: + registry: quay.io + repository: codefresh/dind + tag: 26.1.4-1.28.7 # use `latest-rootless/rootless/26.1.4-1.28.7-rootless` tags for rootless-dind + pullPolicy: IfNotPresent + # -- Set dind resources. + resources: + requests: null + limits: + cpu: 400m + memory: 800Mi + # -- PV claim spec parametes. + pvcs: + # -- Default dind PVC parameters + dind: + # -- PVC name prefix. + # Keep `dind` as default! Don't change! + name: dind + # -- PVC storage class name. + # Change ONLY if you need to use storage class NOT from Codefresh volume-provisioner + storageClassName: '{{ include "dind-volume-provisioner.storageClassName" . }}' + # -- PVC size. + volumeSize: 16Gi + # -- PV reuse selector. + # Ref: https://codefresh.io/docs/docs/installation/codefresh-runner/#volume-reuse-policy + reuseVolumeSelector: codefresh-app,io.codefresh.accountName + reuseVolumeSortOrder: pipeline_id + # -- PV annotations. + annotations: {} + # E.g.: + # annotations: + # codefresh.io/volume-retention: 7d + # -- Set additional env vars. + env: + DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE: true + # -- Set pod annotations. + podAnnotations: {} + # -- Set pod labels. + podLabels: {} + # -- Set node selector. + nodeSelector: {} + # -- Set affinity + affinity: {} + # -- Set tolerations. + tolerations: [] + # -- Set scheduler name. + schedulerName: "" + # -- Set service account for pod. + serviceAccount: codefresh-engine + # -- Keep `true` as default! + userAccess: true + # -- Add extra volumes + userVolumes: {} + # E.g.: + # userVolumes: + # regctl-docker-registry: + # name: regctl-docker-registry + # secret: + # items: + # - key: .dockerconfigjson + # path: config.json + # secretName: regctl-docker-registry + # optional: true + # -- Add extra volume mounts + userVolumeMounts: {} + # E.g.: + # userVolumeMounts: + # regctl-docker-registry: + # name: regctl-docker-registry + # mountPath: /home/appuser/.docker/ + # readOnly: true + + # -- Parameters for Engine pod (aka "pipeline" orchestrator). + engine: + # -- Set image. + image: + registry: quay.io + repository: codefresh/engine + tag: 1.174.7 + pullPolicy: IfNotPresent + # -- Set container command. + command: + - npm + - run + - start + # -- Set resources. + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 1000m + memory: 2048Mi + # -- Set system(base) runtime images. + # @default -- See below. + runtimeImages: + COMPOSE_IMAGE: quay.io/codefresh/compose:v2.28.1-1.5.0 + CONTAINER_LOGGER_IMAGE: quay.io/codefresh/cf-container-logger:1.11.6 + DOCKER_BUILDER_IMAGE: quay.io/codefresh/cf-docker-builder:1.3.13 + DOCKER_PULLER_IMAGE: quay.io/codefresh/cf-docker-puller:8.0.17 + DOCKER_PUSHER_IMAGE: quay.io/codefresh/cf-docker-pusher:6.0.16 + DOCKER_TAG_PUSHER_IMAGE: quay.io/codefresh/cf-docker-tag-pusher:1.3.14 + FS_OPS_IMAGE: quay.io/codefresh/fs-ops:1.2.3 + GIT_CLONE_IMAGE: quay.io/codefresh/cf-git-cloner:10.1.28 + KUBE_DEPLOY: quay.io/codefresh/cf-deploy-kubernetes:16.1.11 + PIPELINE_DEBUGGER_IMAGE: quay.io/codefresh/cf-debugger:1.3.0 + TEMPLATE_ENGINE: quay.io/codefresh/pikolo:0.14.1 + CR_6177_FIXER: 'quay.io/codefresh/alpine:edge' + GC_BUILDER_IMAGE: 'quay.io/codefresh/cf-gc-builder:0.5.3' + COSIGN_IMAGE_SIGNER_IMAGE: 'quay.io/codefresh/cf-cosign-image-signer:2.4.0-cf.2' + # -- Set additional env vars. + env: + # -- Interval to check the exec status in the container-logger + CONTAINER_LOGGER_EXEC_CHECK_INTERVAL_MS: 1000 + # -- Timeout while doing requests to the Docker daemon + DOCKER_REQUEST_TIMEOUT_MS: 30000 + # -- If "true", composition images will be pulled sequentially + FORCE_COMPOSE_SERIAL_PULL: false + # -- Level of logging for engine + LOGGER_LEVEL: debug + # -- Enable debug-level logging of outgoing HTTP/HTTPS requests + LOG_OUTGOING_HTTP_REQUESTS: false + # -- Enable emitting metrics from engine + METRICS_PROMETHEUS_ENABLED: true + # -- Enable legacy metrics + METRICS_PROMETHEUS_ENABLE_LEGACY_METRICS: false + # -- Enable collecting process metrics + METRICS_PROMETHEUS_COLLECT_PROCESS_METRICS: false + # -- Host for Prometheus metrics server + METRICS_PROMETHEUS_HOST: '0.0.0.0' + # -- Port for Prometheus metrics server + METRICS_PROMETHEUS_PORT: 9100 + # -- Set workflow limits. + workflowLimits: + # -- Maximum time allowed to the engine to wait for the pre-steps (aka "Initializing Process") to succeed; seconds. + MAXIMUM_ALLOWED_TIME_BEFORE_PRE_STEPS_SUCCESS: 600 + # -- Maximum time for workflow execution; seconds. + MAXIMUM_ALLOWED_WORKFLOW_AGE_BEFORE_TERMINATION: 86400 + # -- Maximum time allowed to workflow to spend in "elected" state; seconds. + MAXIMUM_ELECTED_STATE_AGE_ALLOWED: 900 + # -- Maximum retry attempts allowed for workflow. + MAXIMUM_RETRY_ATTEMPTS_ALLOWED: 20 + # -- Maximum time allowed to workflow to spend in "terminating" state until force terminated; seconds. + MAXIMUM_TERMINATING_STATE_AGE_ALLOWED: 900 + # -- Maximum time allowed to workflow to spend in "terminating" state without logs activity until force terminated; seconds. + MAXIMUM_TERMINATING_STATE_AGE_ALLOWED_WITHOUT_UPDATE: 300 + # -- Time since the last health check report after which workflow is terminated; seconds. + TIME_ENGINE_INACTIVE_UNTIL_TERMINATION: 300 + # -- Time since the last health check report after which the engine is considered unhealthy; seconds. + TIME_ENGINE_INACTIVE_UNTIL_UNHEALTHY: 60 + # -- Time since the last workflow logs activity after which workflow is terminated; seconds. + TIME_INACTIVE_UNTIL_TERMINATION: 2700 + # -- Set pod annotations. + podAnnotations: {} + # -- Set pod labels. + podLabels: {} + # -- Set node selector. + nodeSelector: {} + # -- Set affinity + affinity: {} + # -- Set tolerations. + tolerations: [] + # -- Set scheduler name. + schedulerName: "" + # -- Set service account for pod. + serviceAccount: codefresh-engine + # -- Set extra env vars + userEnvVars: [] + # E.g. + # userEnvVars: + # - name: GITHUB_TOKEN + # valueFrom: + # secretKeyRef: + # name: github-token + # key: token + + # -- Parameters for `runtime-patch` post-upgrade/install hook + # @default -- See below + patch: + enabled: true + image: + registry: quay.io + repository: codefresh/cli + tag: 0.85.0-rootless + rbac: + enabled: true + annotations: {} + affinity: {} + nodeSelector: {} + podSecurityContext: {} + resources: {} + tolerations: [] + ttlSecondsAfterFinished: 180 + env: + HOME: /tmp + + # -- Parameters for `gencerts-dind` post-upgrade/install hook + # @default -- See below + gencerts: + enabled: true + image: + registry: quay.io + repository: codefresh/kubectl + tag: 1.28.4 + rbac: + enabled: true + annotations: {} + affinity: {} + nodeSelector: {} + podSecurityContext: {} + resources: {} + tolerations: [] + ttlSecondsAfterFinished: 180 + + # -- DinD pod daemon config + # @default -- See below + dindDaemon: + hosts: + - unix:///var/run/docker.sock + - tcp://0.0.0.0:1300 + tlsverify: true + tls: true + tlscacert: /etc/ssl/cf-client/ca.pem + tlscert: /etc/ssl/cf/server-cert.pem + tlskey: /etc/ssl/cf/server-key.pem + insecure-registries: + - 192.168.99.100:5000 + metrics-addr: 0.0.0.0:9323 + experimental: true + +# App-Proxy parameters +# Ref: https://codefresh.io/docs/docs/installation/codefresh-runner/#app-proxy-installation +# @default -- See below +appProxy: + # -- Enable app-proxy + enabled: false + # -- Set number of pods + replicasCount: 1 + # -- Upgrade strategy + updateStrategy: + type: RollingUpdate + # -- Set pod annotations + podAnnotations: {} + + # -- Set image + image: + registry: quay.io + repository: codefresh/cf-app-proxy + tag: 0.0.47 + # -- Add additional env vars + env: {} + + # Set app-proxy ingress parameters + # @default -- See below + ingress: + # -- Set path prefix for ingress (keep empty for default `/` path) + pathPrefix: "" + # -- Set ingress class + class: "" + # -- Set DNS hostname the ingress will use + host: "" + # -- Set k8s tls secret for the ingress object + tlsSecret: "" + # -- Set extra annotations for ingress object + annotations: {} + # E.g. + # ingress: + # pathPrefix: "/cf-app-proxy" + # class: "nginx" + # host: "mydomain.com" + # tlsSecret: "tls-cert-app-proxy" + # annotations: + # nginx.ingress.kubernetes.io/whitelist-source-range: 123.123.123.123/130 + + # -- Service Account parameters + serviceAccount: + # -- Create service account + create: true + # -- Override service account name + name: "" + # -- Use Role(true)/ClusterRole(true) + namespaced: true + # -- Additional service account annotations + annotations: {} + + # -- RBAC parameters + rbac: + # -- Create RBAC resources + create: true + # -- Use Role(true)/ClusterRole(true) + namespaced: true + # -- Add custom rule to the role + rules: [] + + # -- Set security context for the pod + podSecurityContext: {} + + # -- Readiness probe configuration + # @default -- See below + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + + # -- Set requests and limits + resources: {} + # -- Set node selector + nodeSelector: {} + # -- Set tolerations + tolerations: [] + # -- Set affinity + affinity: {} + +# Monitor parameters +# @default -- See below +monitor: + # -- Enable monitor + # Ref: https://codefresh.io/docs/docs/installation/codefresh-runner/#install-monitoring-component + enabled: false + + # -- Set number of pods + replicasCount: 1 + # -- Upgrade strategy + updateStrategy: + type: RollingUpdate + # -- Set pod annotations + podAnnotations: {} + + # -- Set image + image: + registry: quay.io + repository: codefresh/cf-k8s-agent + tag: 1.3.17 + # -- Add additional env vars + env: {} + + # -- Service Account parameters + serviceAccount: + # -- Create service account + create: true + # -- Override service account name + name: "" + # -- Additional service account annotations + annotations: {} + + # -- RBAC parameters + rbac: + # -- Create RBAC resources + create: true + # -- Use Role(true)/ClusterRole(true) + namespaced: true + # -- Add custom rule to the role + rules: [] + + # -- Readiness probe configuration + # @default -- See below + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + + podSecurityContext: {} + + # -- Set node selector + nodeSelector: {} + # -- Set resources + resources: {} + # -- Set tolerations + tolerations: [] + # -- Set affinity + affinity: {} + +# -- Add serviceMonitor +# @default -- See below +serviceMonitor: + main: + # -- Enable service monitor for dind pods + enabled: false + nameOverride: dind + selector: + matchLabels: + app: dind + endpoints: + - path: /metrics + targetPort: 9100 + relabelings: + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + +# -- Add podMonitor (for engine pods) +# @default -- See below +podMonitor: + main: + # -- Enable pod monitor for engine pods + enabled: false + nameOverride: engine + selector: + matchLabels: + app: runtime + podMetricsEndpoints: + - path: /metrics + targetPort: 9100 + + runner: + # -- Enable pod monitor for runner pod + enabled: false + nameOverride: runner + selector: + matchLabels: + codefresh.io/application: runner + podMetricsEndpoints: + - path: /metrics + targetPort: 8080 + + volume-provisioner: + # -- Enable pod monitor for volumeProvisioner pod + enabled: false + nameOverride: volume-provisioner + selector: + matchLabels: + codefresh.io/application: volume-provisioner + podMetricsEndpoints: + - path: /metrics + targetPort: 8080 + +# -- Event exporter parameters +# @default -- See below +event-exporter: + # -- Enable event-exporter + enabled: false + # -- Set number of pods + replicasCount: 1 + # -- Upgrade strategy + updateStrategy: + type: Recreate + # -- Set pod annotations + podAnnotations: {} + + # -- Set image + image: + registry: docker.io + repository: codefresh/k8s-event-exporter + tag: latest + # -- Add additional env vars + env: {} + + # -- Service Account parameters + serviceAccount: + # -- Create service account + create: true + # -- Override service account name + name: "" + # -- Additional service account annotations + annotations: {} + + # -- RBAC parameters + rbac: + # -- Create RBAC resources + create: true + # -- Add custom rule to the role + rules: [] + + # -- Set security context for the pod + # @default -- See below + podSecurityContext: + enabled: false + + # -- Set node selector + nodeSelector: {} + # -- Set resources + resources: {} + # -- Set tolerations + tolerations: [] + # -- Set affinity + affinity: {} + +# -- Array of extra objects to deploy with the release +extraResources: [] +# E.g. +# extraResources: +# - apiVersion: rbac.authorization.k8s.io/v1 +# kind: ClusterRole +# metadata: +# name: codefresh-role +# rules: +# - apiGroups: [ "*"] +# resources: ["*"] +# verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +# - apiVersion: v1 +# kind: ServiceAccount +# metadata: +# name: codefresh-user +# namespace: "{{ .Release.Namespace }}" +# - apiVersion: rbac.authorization.k8s.io/v1 +# kind: ClusterRoleBinding +# metadata: +# name: codefresh-user +# roleRef: +# apiGroup: rbac.authorization.k8s.io +# kind: ClusterRole +# name: codefresh-role +# subjects: +# - kind: ServiceAccount +# name: codefresh-user +# namespace: "{{ .Release.Namespace }}" +# - apiVersion: v1 +# kind: Secret +# type: kubernetes.io/service-account-token +# metadata: +# name: codefresh-user-token +# namespace: "{{ .Release.Namespace }}" +# annotations: +# kubernetes.io/service-account.name: "codefresh-user" diff --git a/charts/external-secrets/external-secrets/0.10.3/Chart.lock b/charts/external-secrets/external-secrets/0.10.3/Chart.lock new file mode 100644 index 000000000..6f01c4874 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: bitwarden-sdk-server + repository: oci://ghcr.io/external-secrets/charts + version: v0.3.1 +digest: sha256:2d01e9083fc32c18dca4f9614625e0172e338a663138c2670e5b911645b6b8ee +generated: "2024-08-29T06:56:01.838539+02:00" diff --git a/charts/external-secrets/external-secrets/0.10.3/Chart.yaml b/charts/external-secrets/external-secrets/0.10.3/Chart.yaml new file mode 100644 index 000000000..5703a2ee6 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/Chart.yaml @@ -0,0 +1,25 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: External Secrets Operator + catalog.cattle.io/kube-version: '>= 1.19.0-0' + catalog.cattle.io/release-name: external-secrets +apiVersion: v2 +appVersion: v0.10.3 +dependencies: +- condition: bitwarden-sdk-server.enabled + name: bitwarden-sdk-server + repository: file://./charts/bitwarden-sdk-server + version: v0.3.1 +description: External secret management for Kubernetes +home: https://github.com/external-secrets/external-secrets +icon: file://assets/icons/external-secrets.png +keywords: +- kubernetes-external-secrets +- secrets +kubeVersion: '>= 1.19.0-0' +maintainers: +- email: kellinmcavoy@gmail.com + name: mcavoyk +name: external-secrets +type: application +version: 0.10.3 diff --git a/charts/external-secrets/external-secrets/0.10.3/README.md b/charts/external-secrets/external-secrets/0.10.3/README.md new file mode 100644 index 000000000..24cda8292 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/README.md @@ -0,0 +1,225 @@ +# External Secrets + +

    external-secrets

    + +[//]: # (README.md generated by gotmpl. DO NOT EDIT.) + +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 0.10.3](https://img.shields.io/badge/Version-0.10.3-informational?style=flat-square) + +External secret management for Kubernetes + +## TL;DR +```bash +helm repo add external-secrets https://charts.external-secrets.io +helm install external-secrets external-secrets/external-secrets +``` + +## Installing the Chart +To install the chart with the release name `external-secrets`: +```bash +helm install external-secrets external-secrets/external-secrets +``` + +### Custom Resources +By default, the chart will install external-secrets CRDs, this can be controlled with `installCRDs` value. + +## Uninstalling the Chart +To uninstall the `external-secrets` deployment: +```bash +helm uninstall external-secrets +``` +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| bitwarden-sdk-server.enabled | bool | `false` | | +| certController.affinity | object | `{}` | | +| certController.create | bool | `true` | Specifies whether a certificate controller deployment be created. | +| certController.deploymentAnnotations | object | `{}` | Annotations to add to Deployment | +| certController.extraArgs | object | `{}` | | +| certController.extraEnv | list | `[]` | | +| certController.extraVolumeMounts | list | `[]` | | +| certController.extraVolumes | list | `[]` | | +| certController.fullnameOverride | string | `""` | | +| certController.hostNetwork | bool | `false` | Run the certController on the host network | +| certController.image.flavour | string | `""` | | +| certController.image.pullPolicy | string | `"IfNotPresent"` | | +| certController.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` | | +| certController.image.tag | string | `""` | | +| certController.imagePullSecrets | list | `[]` | | +| certController.log | object | `{"level":"info","timeEncoding":"epoch"}` | Specifices Log Params to the Webhook | +| certController.metrics.listen.port | int | `8080` | | +| certController.metrics.service.annotations | object | `{}` | Additional service annotations | +| certController.metrics.service.enabled | bool | `false` | Enable if you use another monitoring tool than Prometheus to scrape the metrics | +| certController.metrics.service.port | int | `8080` | Metrics service port to scrape | +| certController.nameOverride | string | `""` | | +| certController.nodeSelector | object | `{}` | | +| certController.podAnnotations | object | `{}` | Annotations to add to Pod | +| certController.podDisruptionBudget | object | `{"enabled":false,"minAvailable":1}` | Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| certController.podLabels | object | `{}` | | +| certController.podSecurityContext.enabled | bool | `true` | | +| certController.priorityClassName | string | `""` | Pod priority class name. | +| certController.rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | +| certController.readinessProbe.address | string | `""` | Address for readiness probe | +| certController.readinessProbe.port | int | `8081` | ReadinessProbe port for kubelet | +| certController.replicaCount | int | `1` | | +| certController.requeueInterval | string | `"5m"` | | +| certController.resources | object | `{}` | | +| certController.revisionHistoryLimit | int | `10` | Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) | +| certController.securityContext.allowPrivilegeEscalation | bool | `false` | | +| certController.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| certController.securityContext.enabled | bool | `true` | | +| certController.securityContext.readOnlyRootFilesystem | bool | `true` | | +| certController.securityContext.runAsNonRoot | bool | `true` | | +| certController.securityContext.runAsUser | int | `1000` | | +| certController.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| certController.serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | +| certController.serviceAccount.automount | bool | `true` | Automounts the service account token in all containers of the pod | +| certController.serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | +| certController.serviceAccount.extraLabels | object | `{}` | Extra Labels to add to the service account. | +| certController.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| certController.tolerations | list | `[]` | | +| certController.topologySpreadConstraints | list | `[]` | | +| commonLabels | object | `{}` | Additional labels added to all helm chart resources. | +| concurrent | int | `1` | Specifies the number of concurrent ExternalSecret Reconciles external-secret executes at a time. | +| controllerClass | string | `""` | If set external secrets will filter matching Secret Stores with the appropriate controller values. | +| crds.annotations | object | `{}` | | +| crds.conversion.enabled | bool | `true` | | +| crds.createClusterExternalSecret | bool | `true` | If true, create CRDs for Cluster External Secret. | +| crds.createClusterSecretStore | bool | `true` | If true, create CRDs for Cluster Secret Store. | +| crds.createPushSecret | bool | `true` | If true, create CRDs for Push Secret. | +| createOperator | bool | `true` | Specifies whether an external secret operator deployment be created. | +| deploymentAnnotations | object | `{}` | Annotations to add to Deployment | +| dnsConfig | object | `{}` | Specifies `dnsOptions` to deployment | +| dnsPolicy | string | `"ClusterFirst"` | Specifies `dnsPolicy` to deployment | +| extendedMetricLabels | bool | `false` | If true external secrets will use recommended kubernetes annotations as prometheus metric labels. | +| extraArgs | object | `{}` | | +| extraContainers | list | `[]` | | +| extraEnv | list | `[]` | | +| extraObjects | list | `[]` | | +| extraVolumeMounts | list | `[]` | | +| extraVolumes | list | `[]` | | +| fullnameOverride | string | `""` | | +| global.affinity | object | `{}` | | +| global.compatibility.openshift.adaptSecurityContext | string | `"auto"` | Manages the securityContext properties to make them compatible with OpenShift. Possible values: auto - Apply configurations if it is detected that OpenShift is the target platform. force - Always apply configurations. disabled - No modification applied. | +| global.nodeSelector | object | `{}` | | +| global.tolerations | list | `[]` | | +| global.topologySpreadConstraints | list | `[]` | | +| hostNetwork | bool | `false` | Run the controller on the host network | +| image.flavour | string | `""` | The flavour of tag you want to use There are different image flavours available, like distroless and ubi. Please see GitHub release notes for image tags for these flavors. By default, the distroless image is used. | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"ghcr.io/external-secrets/external-secrets"` | | +| image.tag | string | `""` | The image tag to use. The default is the chart appVersion. | +| imagePullSecrets | list | `[]` | | +| installCRDs | bool | `true` | If set, install and upgrade CRDs through helm chart. | +| leaderElect | bool | `false` | If true, external-secrets will perform leader election between instances to ensure no more than one instance of external-secrets operates at a time. | +| log | object | `{"level":"info","timeEncoding":"epoch"}` | Specifices Log Params to the Webhook | +| metrics.listen.port | int | `8080` | | +| metrics.service.annotations | object | `{}` | Additional service annotations | +| metrics.service.enabled | bool | `false` | Enable if you use another monitoring tool than Prometheus to scrape the metrics | +| metrics.service.port | int | `8080` | Metrics service port to scrape | +| nameOverride | string | `""` | | +| namespaceOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | Annotations to add to Pod | +| podDisruptionBudget | object | `{"enabled":false,"minAvailable":1}` | Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| podLabels | object | `{}` | | +| podSecurityContext.enabled | bool | `true` | | +| podSpecExtra | object | `{}` | Any extra pod spec on the deployment | +| priorityClassName | string | `""` | Pod priority class name. | +| processClusterExternalSecret | bool | `true` | if true, the operator will process cluster external secret. Else, it will ignore them. | +| processClusterStore | bool | `true` | if true, the operator will process cluster store. Else, it will ignore them. | +| processPushSecret | bool | `true` | if true, the operator will process push secret. Else, it will ignore them. | +| rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | +| rbac.servicebindings.create | bool | `true` | Specifies whether a clusterrole to give servicebindings read access should be created. | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| revisionHistoryLimit | int | `10` | Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) | +| scopedNamespace | string | `""` | If set external secrets are only reconciled in the provided namespace | +| scopedRBAC | bool | `false` | Must be used with scopedNamespace. If true, create scoped RBAC roles under the scoped namespace and implicitly disable cluster stores and cluster external secrets | +| securityContext.allowPrivilegeEscalation | bool | `false` | | +| securityContext.capabilities.drop[0] | string | `"ALL"` | | +| securityContext.enabled | bool | `true` | | +| securityContext.readOnlyRootFilesystem | bool | `true` | | +| securityContext.runAsNonRoot | bool | `true` | | +| securityContext.runAsUser | int | `1000` | | +| securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| service.ipFamilies | list | `[]` | Sets the families that should be supported and the order in which they should be applied to ClusterIP as well. Can be IPv4 and/or IPv6. | +| service.ipFamilyPolicy | string | `""` | Set the ip family policy to configure dual-stack see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services) | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | +| serviceAccount.automount | bool | `true` | Automounts the service account token in all containers of the pod | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | +| serviceAccount.extraLabels | object | `{}` | Extra Labels to add to the service account. | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| serviceMonitor.additionalLabels | object | `{}` | Additional labels | +| serviceMonitor.enabled | bool | `false` | Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics | +| serviceMonitor.honorLabels | bool | `false` | Let prometheus add an exported_ prefix to conflicting labels | +| serviceMonitor.interval | string | `"30s"` | Interval to scrape metrics | +| serviceMonitor.metricRelabelings | list | `[]` | Metric relabel configs to apply to samples before ingestion. [Metric Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) | +| serviceMonitor.namespace | string | `""` | namespace where you want to install ServiceMonitors | +| serviceMonitor.relabelings | list | `[]` | Relabel configs to apply to samples before ingestion. [Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) | +| serviceMonitor.scrapeTimeout | string | `"25s"` | Timeout if metrics can't be retrieved in given time interval | +| tolerations | list | `[]` | | +| topologySpreadConstraints | list | `[]` | | +| webhook.affinity | object | `{}` | | +| webhook.certCheckInterval | string | `"5m"` | Specifices the time to check if the cert is valid | +| webhook.certDir | string | `"/tmp/certs"` | | +| webhook.certManager.addInjectorAnnotations | bool | `true` | Automatically add the cert-manager.io/inject-ca-from annotation to the webhooks and CRDs. As long as you have the cert-manager CA Injector enabled, this will automatically setup your webhook's CA to the one used by cert-manager. See https://cert-manager.io/docs/concepts/ca-injector | +| webhook.certManager.cert.annotations | object | `{}` | Add extra annotations to the Certificate resource. | +| webhook.certManager.cert.create | bool | `true` | Create a certificate resource within this chart. See https://cert-manager.io/docs/usage/certificate/ | +| webhook.certManager.cert.duration | string | `"8760h"` | Set the requested duration (i.e. lifetime) of the Certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec One year by default. | +| webhook.certManager.cert.issuerRef | object | `{"group":"cert-manager.io","kind":"Issuer","name":"my-issuer"}` | For the Certificate created by this chart, setup the issuer. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.IssuerSpec | +| webhook.certManager.cert.renewBefore | string | `""` | How long before the currently issued certificate’s expiry cert-manager should renew the certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec Note that renewBefore should be greater than .webhook.lookaheadInterval since the webhook will check this far in advance that the certificate is valid. | +| webhook.certManager.enabled | bool | `false` | Enabling cert-manager support will disable the built in secret and switch to using cert-manager (installed separately) to automatically issue and renew the webhook certificate. This chart does not install cert-manager for you, See https://cert-manager.io/docs/ | +| webhook.create | bool | `true` | Specifies whether a webhook deployment be created. | +| webhook.deploymentAnnotations | object | `{}` | Annotations to add to Deployment | +| webhook.extraArgs | object | `{}` | | +| webhook.extraEnv | list | `[]` | | +| webhook.extraVolumeMounts | list | `[]` | | +| webhook.extraVolumes | list | `[]` | | +| webhook.failurePolicy | string | `"Fail"` | Specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore | +| webhook.fullnameOverride | string | `""` | | +| webhook.hostNetwork | bool | `false` | Specifies if webhook pod should use hostNetwork or not. | +| webhook.image.flavour | string | `""` | The flavour of tag you want to use | +| webhook.image.pullPolicy | string | `"IfNotPresent"` | | +| webhook.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` | | +| webhook.image.tag | string | `""` | The image tag to use. The default is the chart appVersion. | +| webhook.imagePullSecrets | list | `[]` | | +| webhook.log | object | `{"level":"info","timeEncoding":"epoch"}` | Specifices Log Params to the Webhook | +| webhook.lookaheadInterval | string | `""` | Specifices the lookaheadInterval for certificate validity | +| webhook.metrics.listen.port | int | `8080` | | +| webhook.metrics.service.annotations | object | `{}` | Additional service annotations | +| webhook.metrics.service.enabled | bool | `false` | Enable if you use another monitoring tool than Prometheus to scrape the metrics | +| webhook.metrics.service.port | int | `8080` | Metrics service port to scrape | +| webhook.nameOverride | string | `""` | | +| webhook.nodeSelector | object | `{}` | | +| webhook.podAnnotations | object | `{}` | Annotations to add to Pod | +| webhook.podDisruptionBudget | object | `{"enabled":false,"minAvailable":1}` | Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| webhook.podLabels | object | `{}` | | +| webhook.podSecurityContext.enabled | bool | `true` | | +| webhook.port | int | `10250` | The port the webhook will listen to | +| webhook.priorityClassName | string | `""` | Pod priority class name. | +| webhook.rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | +| webhook.readinessProbe.address | string | `""` | Address for readiness probe | +| webhook.readinessProbe.port | int | `8081` | ReadinessProbe port for kubelet | +| webhook.replicaCount | int | `1` | | +| webhook.resources | object | `{}` | | +| webhook.revisionHistoryLimit | int | `10` | Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) | +| webhook.secretAnnotations | object | `{}` | Annotations to add to Secret | +| webhook.securityContext.allowPrivilegeEscalation | bool | `false` | | +| webhook.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| webhook.securityContext.enabled | bool | `true` | | +| webhook.securityContext.readOnlyRootFilesystem | bool | `true` | | +| webhook.securityContext.runAsNonRoot | bool | `true` | | +| webhook.securityContext.runAsUser | int | `1000` | | +| webhook.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| webhook.serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | +| webhook.serviceAccount.automount | bool | `true` | Automounts the service account token in all containers of the pod | +| webhook.serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | +| webhook.serviceAccount.extraLabels | object | `{}` | Extra Labels to add to the service account. | +| webhook.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| webhook.tolerations | list | `[]` | | +| webhook.topologySpreadConstraints | list | `[]` | | diff --git a/charts/external-secrets/external-secrets/0.10.3/app-readme.md b/charts/external-secrets/external-secrets/0.10.3/app-readme.md new file mode 100644 index 000000000..2a28bc399 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/app-readme.md @@ -0,0 +1,7 @@ +**External Secrets Operator** is a Kubernetes operator that integrates external secret management systems like [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), [HashiCorp Vault](https://www.vaultproject.io/), [Google Secrets Manager](https://cloud.google.com/secret-manager), [Azure Key Vault](https://azure.microsoft.com/en-us/services/key-vault/) and many more. +The operator reads information from external APIs and automatically injects the values into a [Kubernetes Secret](https://kubernetes.io/docs/concepts/configuration/secret/). + +### What is the goal of External Secrets Operator? + +The goal of External Secrets Operator is to synchronize secrets from external APIs into Kubernetes. ESO is a collection of custom API resources - `ExternalSecret`, `SecretStore` and `ClusterSecretStore` that provide a user-friendly abstraction for the external API that stores and manages the lifecycle of the secrets for you. + diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/.helmignore b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/Chart.yaml b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/Chart.yaml new file mode 100644 index 000000000..64d6f3853 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: v0.3.1 +description: A Helm chart for Kubernetes +name: bitwarden-sdk-server +type: application +version: v0.3.1 diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/NOTES.txt b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/NOTES.txt new file mode 100644 index 000000000..46b671c6a --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "bitwarden-sdk-server.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "bitwarden-sdk-server.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "bitwarden-sdk-server.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "bitwarden-sdk-server.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/_helpers.tpl b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/_helpers.tpl new file mode 100644 index 000000000..a5e0da3cc --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "bitwarden-sdk-server.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "bitwarden-sdk-server.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "bitwarden-sdk-server.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "bitwarden-sdk-server.labels" -}} +helm.sh/chart: {{ include "bitwarden-sdk-server.chart" . }} +{{ include "bitwarden-sdk-server.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "bitwarden-sdk-server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "bitwarden-sdk-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "bitwarden-sdk-server.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "bitwarden-sdk-server.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/deployment.yaml b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/deployment.yaml new file mode 100644 index 000000000..06e28820a --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/deployment.yaml @@ -0,0 +1,77 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "bitwarden-sdk-server.fullname" . }} + labels: + {{- include "bitwarden-sdk-server.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "bitwarden-sdk-server.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "bitwarden-sdk-server.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "bitwarden-sdk-server.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + {{- if not .Values.image.tls.enabled }} + args: + - --insecure + {{- end }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.image.tls.enabled }} + volumeMounts: + {{- toYaml .Values.image.tls.volumeMounts | nindent 10 }} + {{- end}} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + livenessProbe: + httpGet: + path: /live + port: http + {{- if .Values.image.tls.enabled }} + scheme: HTTPS + {{- end }} + readinessProbe: + httpGet: + path: /ready + port: http + {{- if .Values.image.tls.enabled }} + scheme: HTTPS + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.image.tls.enabled }} + volumes: + {{- toYaml .Values.image.tls.volumes | nindent 8 }} + {{- end}} diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/service.yaml b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/service.yaml new file mode 100644 index 000000000..88e2d668b --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "bitwarden-sdk-server.fullname" . }} + labels: + {{- include "bitwarden-sdk-server.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + name: http + selector: + {{- include "bitwarden-sdk-server.selectorLabels" . | nindent 4 }} diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/serviceaccount.yaml b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/serviceaccount.yaml new file mode 100644 index 000000000..fef7bad65 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "bitwarden-sdk-server.serviceAccountName" . }} + labels: + {{- include "bitwarden-sdk-server.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/tests/__snapshot__/deployment_test.yaml.snap b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/tests/__snapshot__/deployment_test.yaml.snap new file mode 100644 index 000000000..2fbcdb118 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/tests/__snapshot__/deployment_test.yaml.snap @@ -0,0 +1,60 @@ +deployment should match snapshot: + 1: | + apiVersion: apps/v1 + kind: Deployment + metadata: + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: bitwarden-sdk-server + app.kubernetes.io/version: 1.16.0 + helm.sh/chart: bitwarden-sdk-server-0.1.0 + name: bitwarden-sdk-server + spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/name: bitwarden-sdk-server + template: + metadata: + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/name: bitwarden-sdk-server + spec: + containers: + - image: ghcr.io/external-secrets/bitwarden-sdk-server:v0.8.0 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /live + port: http + scheme: HTTPS + name: bitwarden-sdk-server + ports: + - containerPort: 9998 + name: http + protocol: TCP + readinessProbe: + httpGet: + path: /ready + port: http + scheme: HTTPS + resources: {} + securityContext: {} + volumeMounts: + - mountPath: /certs + name: bitwarden-tls-certs + securityContext: {} + serviceAccountName: bitwarden-sdk-server + volumes: + - name: bitwarden-tls-certs + secret: + items: + - key: tls.crt + path: cert.pem + - key: tls.key + path: key.pem + - key: ca.crt + path: ca.pem + secretName: bitwarden-tls-certs diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/tests/deployment_test.yaml b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/tests/deployment_test.yaml new file mode 100644 index 000000000..bb4e2f4f5 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/tests/deployment_test.yaml @@ -0,0 +1,9 @@ +suite: test deployment +templates: + - deployment.yaml +tests: + - it: deployment should match snapshot + set: + image.tag: v0.8.0 + asserts: + - matchSnapshot: {} diff --git a/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/values.yaml b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/values.yaml new file mode 100644 index 000000000..f0424afba --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/charts/bitwarden-sdk-server/values.yaml @@ -0,0 +1,98 @@ +# Default values for bitwarden-sdk-server. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: ghcr.io/external-secrets/bitwarden-sdk-server + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + tls: + enabled: true + volumeMounts: + - mountPath: "/certs" + name: "bitwarden-tls-certs" + volumes: + - name: "bitwarden-tls-certs" + secret: + secretName: "bitwarden-tls-certs" + items: + - key: "tls.crt" + path: "cert.pem" + - key: "tls.key" + path: "key.pem" + - key: "ca.crt" + path: "ca.pem" + +imagePullSecrets: [] +nameOverride: "bitwarden-sdk-server" +fullnameOverride: "bitwarden-sdk-server" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 9998 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/external-secrets/external-secrets/0.10.3/questions.yaml b/charts/external-secrets/external-secrets/0.10.3/questions.yaml new file mode 100644 index 000000000..31008999d --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/questions.yaml @@ -0,0 +1,8 @@ +questions: +- variable: installCRDs + default: false + required: true + description: "If true, Install and upgrade CRDs through helm chart" + type: boolean + label: Install CRDs + diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/NOTES.txt b/charts/external-secrets/external-secrets/0.10.3/templates/NOTES.txt new file mode 100644 index 000000000..ffa0fc7e1 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/NOTES.txt @@ -0,0 +1,7 @@ +external-secrets has been deployed successfully in namespace {{ template "external-secrets.namespace" . }}! + +In order to begin using ExternalSecrets, you will need to set up a SecretStore +or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore). + +More information on the different types of SecretStores and how to configure them +can be found in our Github: {{ .Chart.Home }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/_helpers.tpl b/charts/external-secrets/external-secrets/0.10.3/templates/_helpers.tpl new file mode 100644 index 000000000..d5eea0759 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/_helpers.tpl @@ -0,0 +1,198 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "external-secrets.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "external-secrets.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Define namespace of chart, useful for multi-namespace deployments +*/}} +{{- define "external-secrets.namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "external-secrets.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "external-secrets.labels" -}} +helm.sh/chart: {{ include "external-secrets.chart" . }} +{{ include "external-secrets.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{- define "external-secrets-webhook.labels" -}} +helm.sh/chart: {{ include "external-secrets.chart" . }} +{{ include "external-secrets-webhook.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{- define "external-secrets-webhook-metrics.labels" -}} +{{ include "external-secrets-webhook.selectorLabels" . }} +app.kubernetes.io/metrics: "webhook" +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{- define "external-secrets-cert-controller.labels" -}} +helm.sh/chart: {{ include "external-secrets.chart" . }} +{{ include "external-secrets-cert-controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{- define "external-secrets-cert-controller-metrics.labels" -}} +{{ include "external-secrets-cert-controller.selectorLabels" . }} +app.kubernetes.io/metrics: "cert-controller" +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "external-secrets.selectorLabels" -}} +app.kubernetes.io/name: {{ include "external-secrets.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- define "external-secrets-webhook.selectorLabels" -}} +app.kubernetes.io/name: {{ include "external-secrets.name" . }}-webhook +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- define "external-secrets-cert-controller.selectorLabels" -}} +app.kubernetes.io/name: {{ include "external-secrets.name" . }}-cert-controller +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{/* +Create the name of the service account to use +*/}} +{{- define "external-secrets.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "external-secrets.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "external-secrets-webhook.serviceAccountName" -}} +{{- if .Values.webhook.serviceAccount.create }} +{{- default "external-secrets-webhook" .Values.webhook.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.webhook.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "external-secrets-cert-controller.serviceAccountName" -}} +{{- if .Values.certController.serviceAccount.create }} +{{- default "external-secrets-cert-controller" .Values.certController.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.certController.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Determine the image to use, including if using a flavour. +*/}} +{{- define "external-secrets.image" -}} +{{- if .image.flavour -}} +{{ printf "%s:%s-%s" .image.repository (.image.tag | default .chartAppVersion) .image.flavour }} +{{- else }} +{{ printf "%s:%s" .image.repository (.image.tag | default .chartAppVersion) }} +{{- end }} +{{- end }} + +{{/* +Renders a complete tree, even values that contains template. +*/}} +{{- define "external-secrets.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{ else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} + +{{/* +Return true if the OpenShift is the detected platform +Usage: +{{- include "external-secrets.isOpenShift" . -}} +*/}} +{{- define "external-secrets.isOpenShift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render the securityContext based on the provided securityContext + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" .Values.securityContext "context" $) -}} +*/}} +{{- define "external-secrets.renderSecurityContext" -}} +{{- $adaptedContext := .securityContext -}} +{{- if .context.Values.global.compatibility -}} + {{- if .context.Values.global.compatibility.openshift -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "external-secrets.isOpenShift" .context)) -}} + {{/* Remove OpenShift managed fields */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .securityContext.seLinuxOptions -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-deployment.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-deployment.yaml new file mode 100644 index 000000000..a843f045a --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-deployment.yaml @@ -0,0 +1,124 @@ +{{- if and .Values.certController.create (not .Values.webhook.certManager.enabled) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} + {{- with .Values.certController.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.certController.replicaCount }} + revisionHistoryLimit: {{ .Values.certController.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.certController.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 8 }} + {{- with .Values.certController.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.certController.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "external-secrets-cert-controller.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.certController.serviceAccount.automount }} + {{- with .Values.certController.podSecurityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + hostNetwork: {{ .Values.certController.hostNetwork }} + containers: + - name: cert-controller + {{- with .Values.certController.securityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 12 }} + {{- end }} + {{- end }} + image: {{ include "external-secrets.image" (dict "chartAppVersion" .Chart.AppVersion "image" .Values.certController.image) | trim }} + imagePullPolicy: {{ .Values.certController.image.pullPolicy }} + args: + - certcontroller + - --crd-requeue-interval={{ .Values.certController.requeueInterval }} + - --service-name={{ include "external-secrets.fullname" . }}-webhook + - --service-namespace={{ template "external-secrets.namespace" . }} + - --secret-name={{ include "external-secrets.fullname" . }}-webhook + - --secret-namespace={{ template "external-secrets.namespace" . }} + - --metrics-addr=:{{ .Values.certController.metrics.listen.port }} + - --healthz-addr={{ .Values.certController.readinessProbe.address }}:{{ .Values.certController.readinessProbe.port }} + - --loglevel={{ .Values.certController.log.level }} + - --zap-time-encoding={{ .Values.certController.log.timeEncoding }} + {{- if not .Values.crds.createClusterSecretStore }} + - --crd-names=externalsecrets.external-secrets.io + - --crd-names=secretstores.external-secrets.io + {{- end }} + {{- if .Values.installCRDs }} + - --enable-partial-cache=true + {{- end }} + {{- range $key, $value := .Values.certController.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.certController.metrics.listen.port }} + protocol: TCP + name: metrics + readinessProbe: + httpGet: + port: {{ .Values.certController.readinessProbe.port }} + path: /readyz + initialDelaySeconds: 20 + periodSeconds: 5 + {{- with .Values.certController.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.certController.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.certController.extraVolumeMounts }} + volumeMounts: + {{- toYaml .Values.certController.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.certController.extraVolumes }} + volumes: + {{- toYaml .Values.certController.extraVolumes | nindent 8 }} + {{- end }} + {{- with .Values.certController.nodeSelector | default .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.certController.affinity | default .Values.global.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.certController.tolerations | default .Values.global.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.certController.topologySpreadConstraints | default .Values.global.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.certController.priorityClassName }} + priorityClassName: {{ .Values.certController.priorityClassName }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-poddisruptionbudget.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-poddisruptionbudget.yaml new file mode 100644 index 000000000..e61cb8ebc --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-poddisruptionbudget.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.certController.create .Values.certController.podDisruptionBudget.enabled (not .Values.webhook.certManager.enabled) }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-pdb + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +spec: + {{- if .Values.certController.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.certController.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.certController.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.certController.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-rbac.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-rbac.yaml new file mode 100644 index 000000000..84a0c110b --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-rbac.yaml @@ -0,0 +1,86 @@ +{{- if and .Values.certController.create .Values.certController.rbac.create (not .Values.webhook.certManager.enabled) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +rules: + - apiGroups: + - "apiextensions.k8s.io" + resources: + - "customresourcedefinitions" + verbs: + - "get" + - "list" + - "watch" + - "update" + - "patch" + - apiGroups: + - "admissionregistration.k8s.io" + resources: + - "validatingwebhookconfigurations" + verbs: + - "list" + - "watch" + - "get" + - apiGroups: + - "admissionregistration.k8s.io" + resources: + - "validatingwebhookconfigurations" + resourceNames: + - "secretstore-validate" + - "externalsecret-validate" + verbs: + - "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" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "external-secrets.fullname" . }}-cert-controller +subjects: + - name: {{ include "external-secrets-cert-controller.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + kind: ServiceAccount +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-service.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-service.yaml new file mode 100644 index 000000000..12cb4f4da --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-service.yaml @@ -0,0 +1,28 @@ +{{- if and .Values.certController.create .Values.certController.metrics.service.enabled (not .Values.webhook.certManager.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.metrics.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.certController.metrics.service.port }} + protocol: TCP + targetPort: metrics + name: metrics + selector: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-serviceaccount.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-serviceaccount.yaml new file mode 100644 index 000000000..6a36f9d71 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/cert-controller-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.certController.create .Values.certController.serviceAccount.create (not .Values.webhook.certManager.enabled) -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "external-secrets-cert-controller.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} + {{- with .Values.certController.serviceAccount.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.certController.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/acraccesstoken.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/acraccesstoken.yaml new file mode 100644 index 000000000..b93e369dc --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/acraccesstoken.yaml @@ -0,0 +1,203 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/clusterexternalsecret.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/clusterexternalsecret.yaml new file mode 100644 index 000000000..53fb399bc --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/clusterexternalsecret.yaml @@ -0,0 +1,666 @@ +{{- if and (.Values.installCRDs) (.Values.crds.createClusterExternalSecret) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/clustersecretstore.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/clustersecretstore.yaml new file mode 100644 index 000000000..8f5aaff81 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/clustersecretstore.yaml @@ -0,0 +1,4601 @@ +{{- if and (.Values.installCRDs) (.Values.crds.createClusterSecretStore) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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 + beyondtrust: + description: Beyondtrust configures this store to sync secrets using Password Safe provider. + properties: + auth: + description: Auth configures how the operator authenticates with Beyondtrust. + properties: + certificate: + description: Content of the certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate. + 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 + certificateKey: + description: Certificate private key (key.pem). For use when authenticating with an OAuth client Id + 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 + clientId: + 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: + 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: + - clientId + - clientSecret + type: object + server: + description: Auth configures how API server works. + properties: + apiUrl: + type: string + clientTimeOutSeconds: + description: Timeout specifies a time limit for requests made by this Client. The timeout includes connection time, any redirects, and reading the response body. Defaults to 45 seconds. + type: integer + retrievalType: + description: The secret retrieval type. SECRET = Secrets Safe (credential, text, file). MANAGED_ACCOUNT = Password Safe account associated with a system. + type: string + separator: + description: A character that separates the folder names. + type: string + verifyCA: + type: boolean + required: + - apiUrl + - verifyCA + type: object + required: + - auth + - server + 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 + caProvider: + description: 'see: https://external-secrets.io/latest/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 + 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 + - 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/ecrauthorizationtoken.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/ecrauthorizationtoken.yaml new file mode 100644 index 000000000..f785add3b --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/ecrauthorizationtoken.yaml @@ -0,0 +1,177 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/externalsecret.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/externalsecret.yaml new file mode 100644 index 000000000..0862f3a1a --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/externalsecret.yaml @@ -0,0 +1,820 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + 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. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/fake.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/fake.yaml new file mode 100644 index 000000000..38cacf603 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/fake.yaml @@ -0,0 +1,86 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/gcraccesstoken.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/gcraccesstoken.yaml new file mode 100644 index 000000000..b71777a75 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/gcraccesstoken.yaml @@ -0,0 +1,138 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/githubaccesstoken.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/githubaccesstoken.yaml new file mode 100644 index 000000000..e1bc7e103 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/githubaccesstoken.yaml @@ -0,0 +1,112 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/password.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/password.yaml new file mode 100644 index 000000000..034ceb3ca --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/password.yaml @@ -0,0 +1,108 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/pushsecret.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/pushsecret.yaml new file mode 100644 index 000000000..f9c12b783 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/pushsecret.yaml @@ -0,0 +1,386 @@ +{{- if and (.Values.installCRDs) (.Values.crds.createPushSecret) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/secretstore.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/secretstore.yaml new file mode 100644 index 000000000..dd756df9c --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/secretstore.yaml @@ -0,0 +1,4601 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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 + beyondtrust: + description: Beyondtrust configures this store to sync secrets using Password Safe provider. + properties: + auth: + description: Auth configures how the operator authenticates with Beyondtrust. + properties: + certificate: + description: Content of the certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate. + 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 + certificateKey: + description: Certificate private key (key.pem). For use when authenticating with an OAuth client Id + 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 + clientId: + 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: + 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: + - clientId + - clientSecret + type: object + server: + description: Auth configures how API server works. + properties: + apiUrl: + type: string + clientTimeOutSeconds: + description: Timeout specifies a time limit for requests made by this Client. The timeout includes connection time, any redirects, and reading the response body. Defaults to 45 seconds. + type: integer + retrievalType: + description: The secret retrieval type. SECRET = Secrets Safe (credential, text, file). MANAGED_ACCOUNT = Password Safe account associated with a system. + type: string + separator: + description: A character that separates the folder names. + type: string + verifyCA: + type: boolean + required: + - apiUrl + - verifyCA + type: object + required: + - auth + - server + 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 + caProvider: + description: 'see: https://external-secrets.io/latest/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 + 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 + - 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/uuid.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/uuid.yaml new file mode 100644 index 000000000..1e8cb6ea3 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/uuid.yaml @@ -0,0 +1,72 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + name: uuids.generators.external-secrets.io +spec: + group: generators.external-secrets.io + names: + categories: + - password + kind: UUID + listKind: UUIDList + plural: uuids + shortNames: + - uuids + singular: uuid + 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: UUIDSpec controls the behavior of the uuid generator. + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/vaultdynamicsecret.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/vaultdynamicsecret.yaml new file mode 100644 index 000000000..6929b9f3c --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/vaultdynamicsecret.yaml @@ -0,0 +1,707 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/crds/webhook.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/crds/webhook.yaml new file mode 100644 index 000000000..8d38d2638 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/crds/webhook.yaml @@ -0,0 +1,157 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- if and .Values.crds.conversion.enabled .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} + controller-gen.kubebuilder.io/version: v0.16.2 + 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: {} +{{- if .Values.crds.conversion.enabled }} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/deployment.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/deployment.yaml new file mode 100644 index 000000000..75a908e63 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/deployment.yaml @@ -0,0 +1,146 @@ +{{- if .Values.createOperator }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "external-secrets.fullname" . }} + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "external-secrets.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "external-secrets.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.serviceAccount.automount }} + {{- with .Values.podSecurityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + hostNetwork: {{ .Values.hostNetwork }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 12 }} + {{- end }} + {{- end }} + image: {{ include "external-secrets.image" (dict "chartAppVersion" .Chart.AppVersion "image" .Values.image) | trim }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if or (.Values.leaderElect) (.Values.scopedNamespace) (.Values.processClusterStore) (.Values.processClusterExternalSecret) (.Values.concurrent) (.Values.extraArgs) }} + args: + {{- if .Values.leaderElect }} + - --enable-leader-election=true + {{- end }} + {{- if .Values.scopedNamespace }} + - --namespace={{ .Values.scopedNamespace }} + {{- end }} + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + - --enable-cluster-store-reconciler=false + - --enable-cluster-external-secret-reconciler=false + {{- else }} + {{- if not .Values.processClusterStore }} + - --enable-cluster-store-reconciler=false + {{- end }} + {{- if not .Values.processClusterExternalSecret }} + - --enable-cluster-external-secret-reconciler=false + {{- end }} + {{- end }} + {{- if not .Values.processPushSecret }} + - --enable-push-secret-reconciler=false + {{- end }} + {{- if .Values.controllerClass }} + - --controller-class={{ .Values.controllerClass }} + {{- end }} + {{- if .Values.extendedMetricLabels }} + - --enable-extended-metric-labels={{ .Values.extendedMetricLabels }} + {{- end }} + {{- if .Values.concurrent }} + - --concurrent={{ .Values.concurrent }} + {{- end }} + {{- range $key, $value := .Values.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + {{- end }} + - --metrics-addr=:{{ .Values.metrics.listen.port }} + - --loglevel={{ .Values.log.level }} + - --zap-time-encoding={{ .Values.log.timeEncoding }} + ports: + - containerPort: {{ .Values.metrics.listen.port }} + protocol: TCP + name: metrics + {{- with .Values.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.extraVolumeMounts }} + volumeMounts: + {{- toYaml .Values.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.extraContainers }} + {{ toYaml .Values.extraContainers | nindent 8}} + {{- end }} + dnsPolicy: {{ .Values.dnsPolicy }} + {{- if .Values.dnsConfig }} + dnsConfig: + {{- toYaml .Values.dnsConfig | nindent 8 }} + {{- end }} + {{- if .Values.extraVolumes }} + volumes: + {{- toYaml .Values.extraVolumes | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector | default .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity | default .Values.global.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations | default .Values.global.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints | default .Values.global.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.podSpecExtra }} + {{- toYaml .Values.podSpecExtra | nindent 6 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/extra-manifests.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/extra-manifests.yaml new file mode 100644 index 000000000..1dfe8f48f --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraObjects }} +--- +{{ include "external-secrets.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/poddisruptionbudget.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/poddisruptionbudget.yaml new file mode 100644 index 000000000..7b75ca3f4 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/poddisruptionbudget.yaml @@ -0,0 +1,19 @@ +{{- if .Values.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "external-secrets.fullname" . }}-pdb + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +spec: + {{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "external-secrets.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/rbac.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/rbac.yaml new file mode 100644 index 000000000..4f4ab48fe --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/rbac.yaml @@ -0,0 +1,301 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-controller + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +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" +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-view + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + 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" +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-edit + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + 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" +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: RoleBinding +{{- else }} +kind: ClusterRoleBinding +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-controller + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + kind: Role + {{- else }} + kind: ClusterRole + {{- end }} + name: {{ include "external-secrets.fullname" . }}-controller +subjects: + - name: {{ include "external-secrets.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + kind: ServiceAccount +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "external-secrets.fullname" . }}-leaderelection + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +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" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "external-secrets.fullname" . }}-leaderelection + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "external-secrets.fullname" . }}-leaderelection +subjects: + - kind: ServiceAccount + name: {{ include "external-secrets.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} +{{- if .Values.rbac.servicebindings.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "external-secrets.fullname" . }}-servicebindings + labels: + servicebinding.io/controller: "true" + {{- include "external-secrets.labels" . | nindent 4 }} +rules: + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + verbs: + - "get" + - "list" + - "watch" +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/service.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/service.yaml new file mode 100644 index 000000000..94859a34e --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/service.yaml @@ -0,0 +1,28 @@ +{{- if .Values.metrics.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.metrics.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.metrics.service.port }} + protocol: TCP + targetPort: metrics + name: metrics + selector: + {{- include "external-secrets.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/serviceaccount.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/serviceaccount.yaml new file mode 100644 index 000000000..ceaa98e1c --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "external-secrets.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/servicemonitor.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/servicemonitor.yaml new file mode 100644 index 000000000..31451791a --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/servicemonitor.yaml @@ -0,0 +1,164 @@ +{{- if and ( .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" ) .Values.serviceMonitor.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.metrics.service.port }} + protocol: TCP + name: metrics + selector: + {{- include "external-secrets.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +{{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-metrics + namespace: {{ .Values.serviceMonitor.namespace | default (include "external-secrets.namespace" .) | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ template "external-secrets.namespace" . }} + endpoints: + - port: metrics + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} +--- +{{- if .Values.webhook.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook-metrics.labels" . | nindent 4 }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.webhook.metrics.service.port }} + protocol: TCP + name: metrics + selector: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} +{{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-webhook-metrics + namespace: {{ .Values.serviceMonitor.namespace | default (include "external-secrets.namespace" .) | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets-webhook-metrics.labels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ template "external-secrets.namespace" . }} + endpoints: + - port: metrics + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} +--- +{{- if .Values.certController.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-cert-controller-metrics.labels" . | nindent 4 }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: {{ .Values.certController.metrics.listen.port }} + protocol: TCP + name: metrics + selector: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +{{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + namespace: {{ .Values.serviceMonitor.namespace | default (include "external-secrets.namespace" .) | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets-cert-controller-metrics.labels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ template "external-secrets.namespace" . }} + endpoints: + - port: metrics + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/validatingwebhook.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/validatingwebhook.yaml new file mode 100644 index 000000000..63b39763f --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/validatingwebhook.yaml @@ -0,0 +1,78 @@ +{{- if .Values.webhook.create }} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: secretstore-validate + labels: + external-secrets.io/component: webhook + {{- with .Values.commonLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} + {{- if and .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + annotations: + cert-manager.io/inject-ca-from: {{ template "external-secrets.namespace" . }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} +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: {{ template "external-secrets.namespace" . }} + name: {{ include "external-secrets.fullname" . }}-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: {{ template "external-secrets.namespace" . }} + name: {{ include "external-secrets.fullname" . }}-webhook + path: /validate-external-secrets-io-v1beta1-clustersecretstore + admissionReviewVersions: ["v1", "v1beta1"] + sideEffects: None + timeoutSeconds: 5 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: externalsecret-validate + labels: + external-secrets.io/component: webhook + {{- with .Values.commonLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} + {{- if and .Values.webhook.certManager.enabled .Values.webhook.certManager.addInjectorAnnotations }} + annotations: + cert-manager.io/inject-ca-from: {{ template "external-secrets.namespace" . }}/{{ include "external-secrets.fullname" . }}-webhook + {{- end }} +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: {{ template "external-secrets.namespace" . }} + name: {{ include "external-secrets.fullname" . }}-webhook + path: /validate-external-secrets-io-v1beta1-externalsecret + admissionReviewVersions: ["v1", "v1beta1"] + sideEffects: None + timeoutSeconds: 5 + failurePolicy: {{ .Values.webhook.failurePolicy}} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/webhook-certificate.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-certificate.yaml new file mode 100644 index 000000000..adb19fd95 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-certificate.yaml @@ -0,0 +1,30 @@ +{{- if and .Values.webhook.create .Values.webhook.certManager.enabled .Values.webhook.certManager.cert.create }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component: webhook + {{- with .Values.webhook.certManager.cert.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + commonName: {{ include "external-secrets.fullname" . }}-webhook + dnsNames: + - {{ include "external-secrets.fullname" . }}-webhook + - {{ include "external-secrets.fullname" . }}-webhook.{{ template "external-secrets.namespace" . }} + - {{ include "external-secrets.fullname" . }}-webhook.{{ template "external-secrets.namespace" . }}.svc + issuerRef: + {{- toYaml .Values.webhook.certManager.cert.issuerRef | nindent 4 }} + {{- with .Values.webhook.certManager.cert.duration }} + duration: {{ . | quote }} + {{- end }} + {{- with .Values.webhook.certManager.cert.renewBefore }} + renewBefore: {{ . | quote }} + {{- end }} + secretName: {{ include "external-secrets.fullname" . }}-webhook +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/webhook-deployment.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-deployment.yaml new file mode 100644 index 000000000..7419a426b --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-deployment.yaml @@ -0,0 +1,128 @@ +{{- if .Values.webhook.create }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + {{- with .Values.webhook.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.webhook.replicaCount }} + revisionHistoryLimit: {{ .Values.webhook.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.webhook.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 8 }} + {{- with .Values.webhook.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.webhook.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + hostNetwork: {{ .Values.webhook.hostNetwork}} + serviceAccountName: {{ include "external-secrets-webhook.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.webhook.serviceAccount.automount }} + {{- with .Values.webhook.podSecurityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + containers: + - name: webhook + {{- with .Values.webhook.securityContext }} + {{- if and (.enabled) (gt (keys . | len) 1) }} + securityContext: + {{- include "external-secrets.renderSecurityContext" (dict "securityContext" . "context" $) | nindent 12 }} + {{- end }} + {{- end }} + image: {{ include "external-secrets.image" (dict "chartAppVersion" .Chart.AppVersion "image" .Values.webhook.image) | trim }} + imagePullPolicy: {{ .Values.webhook.image.pullPolicy }} + args: + - webhook + - --port={{ .Values.webhook.port }} + - --dns-name={{ include "external-secrets.fullname" . }}-webhook.{{ template "external-secrets.namespace" . }}.svc + - --cert-dir={{ .Values.webhook.certDir }} + - --check-interval={{ .Values.webhook.certCheckInterval }} + - --metrics-addr=:{{ .Values.webhook.metrics.listen.port }} + - --healthz-addr={{ .Values.webhook.readinessProbe.address }}:{{ .Values.webhook.readinessProbe.port }} + - --loglevel={{ .Values.webhook.log.level }} + - --zap-time-encoding={{ .Values.webhook.log.timeEncoding }} + {{- if .Values.webhook.lookaheadInterval }} + - --lookahead-interval={{ .Values.webhook.lookaheadInterval }} + {{- end }} + {{- range $key, $value := .Values.webhook.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.webhook.metrics.listen.port }} + protocol: TCP + name: metrics + - containerPort: {{ .Values.webhook.port }} + protocol: TCP + name: webhook + readinessProbe: + httpGet: + port: {{ .Values.webhook.readinessProbe.port }} + path: /readyz + initialDelaySeconds: 20 + periodSeconds: 5 + {{- with .Values.webhook.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.webhook.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: certs + mountPath: {{ .Values.webhook.certDir }} + readOnly: true + {{- if .Values.webhook.extraVolumeMounts }} + {{- toYaml .Values.webhook.extraVolumeMounts | nindent 12 }} + {{- end }} + volumes: + - name: certs + secret: + secretName: {{ include "external-secrets.fullname" . }}-webhook + {{- if .Values.webhook.extraVolumes }} + {{- toYaml .Values.webhook.extraVolumes | nindent 8 }} + {{- end }} + {{- with .Values.webhook.nodeSelector | default .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.affinity | default .Values.global.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.tolerations | default .Values.global.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.topologySpreadConstraints | default .Values.global.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.webhook.priorityClassName }} + priorityClassName: {{ .Values.webhook.priorityClassName }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/webhook-poddisruptionbudget.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-poddisruptionbudget.yaml new file mode 100644 index 000000000..58345ba68 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-poddisruptionbudget.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.webhook.create .Values.webhook.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook-pdb + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component: webhook +spec: + {{- if .Values.webhook.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.webhook.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.webhook.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.webhook.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/webhook-secret.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-secret.yaml new file mode 100644 index 000000000..fa7760ed6 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-secret.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.webhook.create (not .Values.webhook.certManager.enabled) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component: webhook + {{- with .Values.webhook.secretAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/webhook-service.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-service.yaml new file mode 100644 index 000000000..59dbddc95 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-service.yaml @@ -0,0 +1,37 @@ +{{- if .Values.webhook.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component: webhook + {{- if .Values.webhook.metrics.service.enabled }} + {{- with .Values.webhook.metrics.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: + type: ClusterIP + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + ports: + - port: 443 + targetPort: {{ .Values.webhook.port }} + protocol: TCP + name: webhook + {{- if .Values.webhook.metrics.service.enabled }} + - port: {{ .Values.webhook.metrics.service.port }} + protocol: TCP + targetPort: metrics + name: metrics + {{- end }} + selector: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/templates/webhook-serviceaccount.yaml b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-serviceaccount.yaml new file mode 100644 index 000000000..193621842 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/templates/webhook-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.webhook.create .Values.webhook.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "external-secrets-webhook.serviceAccountName" . }} + namespace: {{ template "external-secrets.namespace" . }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + {{- with .Values.webhook.serviceAccount.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.webhook.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets/external-secrets/0.10.3/values.schema.json b/charts/external-secrets/external-secrets/0.10.3/values.schema.json new file mode 100644 index 000000000..08cef96a3 --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/values.schema.json @@ -0,0 +1,905 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "properties": { + "affinity": { + "properties": {}, + "type": "object" + }, + "bitwarden-sdk-server": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + }, + "certController": { + "properties": { + "affinity": { + "properties": {}, + "type": "object" + }, + "create": { + "type": "boolean" + }, + "deploymentAnnotations": { + "properties": {}, + "type": "object" + }, + "extraArgs": { + "properties": {}, + "type": "object" + }, + "extraEnv": { + "type": "array" + }, + "extraVolumeMounts": { + "type": "array" + }, + "extraVolumes": { + "type": "array" + }, + "fullnameOverride": { + "type": "string" + }, + "hostNetwork": { + "type": "boolean" + }, + "image": { + "properties": { + "flavour": { + "type": "string" + }, + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + }, + "type": "object" + }, + "imagePullSecrets": { + "type": "array" + }, + "log": { + "properties": { + "level": { + "type": "string" + }, + "timeEncoding": { + "type": "string" + } + }, + "type": "object" + }, + "metrics": { + "properties": { + "listen": { + "properties": { + "port": { + "type": "integer" + } + }, + "type": "object" + }, + "service": { + "properties": { + "annotations": { + "properties": {}, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "nameOverride": { + "type": "string" + }, + "nodeSelector": { + "properties": {}, + "type": "object" + }, + "podAnnotations": { + "properties": {}, + "type": "object" + }, + "podDisruptionBudget": { + "properties": { + "enabled": { + "type": "boolean" + }, + "minAvailable": { + "type": "integer" + } + }, + "type": "object" + }, + "podLabels": { + "properties": {}, + "type": "object" + }, + "podSecurityContext": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + }, + "priorityClassName": { + "type": "string" + }, + "rbac": { + "properties": { + "create": { + "type": "boolean" + } + }, + "type": "object" + }, + "readinessProbe": { + "properties": { + "address": { + "type": "string" + }, + "port": { + "type": "integer" + } + }, + "type": "object" + }, + "replicaCount": { + "type": "integer" + }, + "requeueInterval": { + "type": "string" + }, + "resources": { + "properties": {}, + "type": "object" + }, + "revisionHistoryLimit": { + "type": "integer" + }, + "securityContext": { + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "properties": { + "drop": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + }, + "seccompProfile": { + "properties": { + "type": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "serviceAccount": { + "properties": { + "annotations": { + "properties": {}, + "type": "object" + }, + "automount": { + "type": "boolean" + }, + "create": { + "type": "boolean" + }, + "extraLabels": { + "properties": {}, + "type": "object" + }, + "name": { + "type": "string" + } + }, + "type": "object" + }, + "tolerations": { + "type": "array" + }, + "topologySpreadConstraints": { + "type": "array" + } + }, + "type": "object" + }, + "commonLabels": { + "properties": {}, + "type": "object" + }, + "concurrent": { + "type": "integer" + }, + "controllerClass": { + "type": "string" + }, + "crds": { + "properties": { + "annotations": { + "properties": {}, + "type": "object" + }, + "conversion": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + }, + "createClusterExternalSecret": { + "type": "boolean" + }, + "createClusterSecretStore": { + "type": "boolean" + }, + "createPushSecret": { + "type": "boolean" + } + }, + "type": "object" + }, + "createOperator": { + "type": "boolean" + }, + "deploymentAnnotations": { + "properties": {}, + "type": "object" + }, + "dnsConfig": { + "properties": {}, + "type": "object" + }, + "dnsPolicy": { + "type": "string" + }, + "extendedMetricLabels": { + "type": "boolean" + }, + "extraArgs": { + "properties": {}, + "type": "object" + }, + "extraContainers": { + "type": "array" + }, + "extraEnv": { + "type": "array" + }, + "extraObjects": { + "type": "array" + }, + "extraVolumeMounts": { + "type": "array" + }, + "extraVolumes": { + "type": "array" + }, + "fullnameOverride": { + "type": "string" + }, + "global": { + "properties": { + "affinity": { + "properties": {}, + "type": "object" + }, + "compatibility": { + "properties": { + "openshift": { + "properties": { + "adaptSecurityContext": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "nodeSelector": { + "properties": {}, + "type": "object" + }, + "tolerations": { + "type": "array" + }, + "topologySpreadConstraints": { + "type": "array" + } + }, + "type": "object" + }, + "hostNetwork": { + "type": "boolean" + }, + "image": { + "properties": { + "flavour": { + "type": "string" + }, + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + }, + "type": "object" + }, + "imagePullSecrets": { + "type": "array" + }, + "installCRDs": { + "type": "boolean" + }, + "leaderElect": { + "type": "boolean" + }, + "log": { + "properties": { + "level": { + "type": "string" + }, + "timeEncoding": { + "type": "string" + } + }, + "type": "object" + }, + "metrics": { + "properties": { + "listen": { + "properties": { + "port": { + "type": "integer" + } + }, + "type": "object" + }, + "service": { + "properties": { + "annotations": { + "properties": {}, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "nameOverride": { + "type": "string" + }, + "namespaceOverride": { + "type": "string" + }, + "nodeSelector": { + "properties": {}, + "type": "object" + }, + "podAnnotations": { + "properties": {}, + "type": "object" + }, + "podDisruptionBudget": { + "properties": { + "enabled": { + "type": "boolean" + }, + "minAvailable": { + "type": "integer" + } + }, + "type": "object" + }, + "podLabels": { + "properties": {}, + "type": "object" + }, + "podSecurityContext": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + }, + "podSpecExtra": { + "properties": {}, + "type": "object" + }, + "priorityClassName": { + "type": "string" + }, + "processClusterExternalSecret": { + "type": "boolean" + }, + "processClusterStore": { + "type": "boolean" + }, + "processPushSecret": { + "type": "boolean" + }, + "rbac": { + "properties": { + "create": { + "type": "boolean" + }, + "servicebindings": { + "properties": { + "create": { + "type": "boolean" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "replicaCount": { + "type": "integer" + }, + "resources": { + "properties": {}, + "type": "object" + }, + "revisionHistoryLimit": { + "type": "integer" + }, + "scopedNamespace": { + "type": "string" + }, + "scopedRBAC": { + "type": "boolean" + }, + "securityContext": { + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "properties": { + "drop": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + }, + "seccompProfile": { + "properties": { + "type": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "service": { + "properties": { + "ipFamilies": { + "type": "array" + }, + "ipFamilyPolicy": { + "type": "string" + } + }, + "type": "object" + }, + "serviceAccount": { + "properties": { + "annotations": { + "properties": {}, + "type": "object" + }, + "automount": { + "type": "boolean" + }, + "create": { + "type": "boolean" + }, + "extraLabels": { + "properties": {}, + "type": "object" + }, + "name": { + "type": "string" + } + }, + "type": "object" + }, + "serviceMonitor": { + "properties": { + "additionalLabels": { + "properties": {}, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "honorLabels": { + "type": "boolean" + }, + "interval": { + "type": "string" + }, + "metricRelabelings": { + "type": "array" + }, + "namespace": { + "type": "string" + }, + "relabelings": { + "type": "array" + }, + "scrapeTimeout": { + "type": "string" + } + }, + "type": "object" + }, + "tolerations": { + "type": "array" + }, + "topologySpreadConstraints": { + "type": "array" + }, + "webhook": { + "properties": { + "affinity": { + "properties": {}, + "type": "object" + }, + "certCheckInterval": { + "type": "string" + }, + "certDir": { + "type": "string" + }, + "certManager": { + "properties": { + "addInjectorAnnotations": { + "type": "boolean" + }, + "cert": { + "properties": { + "annotations": { + "properties": {}, + "type": "object" + }, + "create": { + "type": "boolean" + }, + "duration": { + "type": "string" + }, + "issuerRef": { + "properties": { + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "type": "object" + }, + "renewBefore": { + "type": "string" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + } + }, + "type": "object" + }, + "create": { + "type": "boolean" + }, + "deploymentAnnotations": { + "properties": {}, + "type": "object" + }, + "extraArgs": { + "properties": {}, + "type": "object" + }, + "extraEnv": { + "type": "array" + }, + "extraVolumeMounts": { + "type": "array" + }, + "extraVolumes": { + "type": "array" + }, + "failurePolicy": { + "type": "string" + }, + "fullnameOverride": { + "type": "string" + }, + "hostNetwork": { + "type": "boolean" + }, + "image": { + "properties": { + "flavour": { + "type": "string" + }, + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + }, + "type": "object" + }, + "imagePullSecrets": { + "type": "array" + }, + "log": { + "properties": { + "level": { + "type": "string" + }, + "timeEncoding": { + "type": "string" + } + }, + "type": "object" + }, + "lookaheadInterval": { + "type": "string" + }, + "metrics": { + "properties": { + "listen": { + "properties": { + "port": { + "type": "integer" + } + }, + "type": "object" + }, + "service": { + "properties": { + "annotations": { + "properties": {}, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "nameOverride": { + "type": "string" + }, + "nodeSelector": { + "properties": {}, + "type": "object" + }, + "podAnnotations": { + "properties": {}, + "type": "object" + }, + "podDisruptionBudget": { + "properties": { + "enabled": { + "type": "boolean" + }, + "minAvailable": { + "type": "integer" + } + }, + "type": "object" + }, + "podLabels": { + "properties": {}, + "type": "object" + }, + "podSecurityContext": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + }, + "port": { + "type": "integer" + }, + "priorityClassName": { + "type": "string" + }, + "rbac": { + "properties": { + "create": { + "type": "boolean" + } + }, + "type": "object" + }, + "readinessProbe": { + "properties": { + "address": { + "type": "string" + }, + "port": { + "type": "integer" + } + }, + "type": "object" + }, + "replicaCount": { + "type": "integer" + }, + "resources": { + "properties": {}, + "type": "object" + }, + "revisionHistoryLimit": { + "type": "integer" + }, + "secretAnnotations": { + "properties": {}, + "type": "object" + }, + "securityContext": { + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "properties": { + "drop": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + }, + "seccompProfile": { + "properties": { + "type": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "serviceAccount": { + "properties": { + "annotations": { + "properties": {}, + "type": "object" + }, + "automount": { + "type": "boolean" + }, + "create": { + "type": "boolean" + }, + "extraLabels": { + "properties": {}, + "type": "object" + }, + "name": { + "type": "string" + } + }, + "type": "object" + }, + "tolerations": { + "type": "array" + }, + "topologySpreadConstraints": { + "type": "array" + } + }, + "type": "object" + } + }, + "type": "object" +} diff --git a/charts/external-secrets/external-secrets/0.10.3/values.yaml b/charts/external-secrets/external-secrets/0.10.3/values.yaml new file mode 100644 index 000000000..19525ad8a --- /dev/null +++ b/charts/external-secrets/external-secrets/0.10.3/values.yaml @@ -0,0 +1,532 @@ +global: + nodeSelector: {} + tolerations: [] + topologySpreadConstraints: [] + affinity: {} + compatibility: + openshift: + # -- Manages the securityContext properties to make them compatible with OpenShift. + # Possible values: + # auto - Apply configurations if it is detected that OpenShift is the target platform. + # force - Always apply configurations. + # disabled - No modification applied. + adaptSecurityContext: auto + +replicaCount: 1 + +bitwarden-sdk-server: + enabled: false + +# -- Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) +revisionHistoryLimit: 10 + +image: + repository: ghcr.io/external-secrets/external-secrets + pullPolicy: IfNotPresent + # -- The image tag to use. The default is the chart appVersion. + tag: "" + # -- The flavour of tag you want to use + # There are different image flavours available, like distroless and ubi. + # Please see GitHub release notes for image tags for these flavors. + # By default, the distroless image is used. + flavour: "" + +# -- If set, install and upgrade CRDs through helm chart. +installCRDs: true + +crds: + # -- If true, create CRDs for Cluster External Secret. + createClusterExternalSecret: true + # -- If true, create CRDs for Cluster Secret Store. + createClusterSecretStore: true + # -- If true, create CRDs for Push Secret. + createPushSecret: true + annotations: {} + conversion: + enabled: true + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" +namespaceOverride: "" + +# -- Additional labels added to all helm chart resources. +commonLabels: {} + +# -- If true, external-secrets will perform leader election between instances to ensure no more +# than one instance of external-secrets operates at a time. +leaderElect: false + +# -- If set external secrets will filter matching +# Secret Stores with the appropriate controller values. +controllerClass: "" + +# -- If true external secrets will use recommended kubernetes +# annotations as prometheus metric labels. +extendedMetricLabels: false + +# -- If set external secrets are only reconciled in the +# provided namespace +scopedNamespace: "" + +# -- Must be used with scopedNamespace. If true, create scoped RBAC roles under the scoped namespace +# and implicitly disable cluster stores and cluster external secrets +scopedRBAC: false + +# -- if true, the operator will process cluster external secret. Else, it will ignore them. +processClusterExternalSecret: true + +# -- if true, the operator will process cluster store. Else, it will ignore them. +processClusterStore: true + +# -- if true, the operator will process push secret. Else, it will ignore them. +processPushSecret: true + +# -- Specifies whether an external secret operator deployment be created. +createOperator: true + +# -- Specifies the number of concurrent ExternalSecret Reconciles external-secret executes at +# a time. +concurrent: 1 +# -- Specifices Log Params to the Webhook +log: + level: info + timeEncoding: epoch +service: + # -- Set the ip family policy to configure dual-stack see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services) + ipFamilyPolicy: "" + # -- Sets the families that should be supported and the order in which they should be applied to ClusterIP as well. Can be IPv4 and/or IPv6. + ipFamilies: [] + +serviceAccount: + # -- Specifies whether a service account should be created. + create: true + # -- Automounts the service account token in all containers of the pod + automount: true + # -- Annotations to add to the service account. + annotations: {} + # -- Extra Labels to add to the service account. + extraLabels: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + +rbac: + # -- Specifies whether role and rolebinding resources should be created. + create: true + + servicebindings: + # -- Specifies whether a clusterrole to give servicebindings read access should be created. + create: true + +## -- Extra environment variables to add to container. +extraEnv: [] + +## -- Map of extra arguments to pass to container. +extraArgs: {} + +## -- Extra volumes to pass to pod. +extraVolumes: [] + +## -- Extra Kubernetes objects to deploy with the helm chart +extraObjects: [] + +## -- Extra volumes to mount to the container. +extraVolumeMounts: [] + +## -- Extra containers to add to the pod. +extraContainers: [] + +# -- Annotations to add to Deployment +deploymentAnnotations: {} + +# -- Annotations to add to Pod +podAnnotations: {} + +podLabels: {} + +podSecurityContext: + enabled: true + # fsGroup: 2000 + +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + enabled: true + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + +resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + +serviceMonitor: + # -- Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics + enabled: false + + # -- namespace where you want to install ServiceMonitors + namespace: "" + + # -- Additional labels + additionalLabels: {} + + # -- Interval to scrape metrics + interval: 30s + + # -- Timeout if metrics can't be retrieved in given time interval + scrapeTimeout: 25s + + # -- Let prometheus add an exported_ prefix to conflicting labels + honorLabels: false + + # -- Metric relabel configs to apply to samples before ingestion. [Metric Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) + metricRelabelings: [] + # - action: replace + # regex: (.*) + # replacement: $1 + # sourceLabels: + # - exported_namespace + # targetLabel: namespace + + # -- Relabel configs to apply to samples before ingestion. [Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + +metrics: + + listen: + port: 8080 + + service: + # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics + enabled: false + + # -- Metrics service port to scrape + port: 8080 + + # -- Additional service annotations + annotations: {} + +nodeSelector: {} + +tolerations: [] + +topologySpreadConstraints: [] + +affinity: {} + +# -- Pod priority class name. +priorityClassName: "" + +# -- Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ +podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1 + +# -- Run the controller on the host network +hostNetwork: false + +webhook: + # -- Specifies whether a webhook deployment be created. + create: true + # -- Specifices the time to check if the cert is valid + certCheckInterval: "5m" + # -- Specifices the lookaheadInterval for certificate validity + lookaheadInterval: "" + replicaCount: 1 + # -- Specifices Log Params to the Webhook + log: + level: info + timeEncoding: epoch + # -- Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) + revisionHistoryLimit: 10 + + certDir: /tmp/certs + # -- Specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore + failurePolicy: Fail + # -- Specifies if webhook pod should use hostNetwork or not. + hostNetwork: false + image: + repository: ghcr.io/external-secrets/external-secrets + pullPolicy: IfNotPresent + # -- The image tag to use. The default is the chart appVersion. + tag: "" + # -- The flavour of tag you want to use + flavour: "" + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + # -- The port the webhook will listen to + port: 10250 + rbac: + # -- Specifies whether role and rolebinding resources should be created. + create: true + serviceAccount: + # -- Specifies whether a service account should be created. + create: true + # -- Automounts the service account token in all containers of the pod + automount: true + # -- Annotations to add to the service account. + annotations: {} + # -- Extra Labels to add to the service account. + extraLabels: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + nodeSelector: {} + + certManager: + # -- Enabling cert-manager support will disable the built in secret and + # switch to using cert-manager (installed separately) to automatically issue + # and renew the webhook certificate. This chart does not install + # cert-manager for you, See https://cert-manager.io/docs/ + enabled: false + # -- Automatically add the cert-manager.io/inject-ca-from annotation to the + # webhooks and CRDs. As long as you have the cert-manager CA Injector + # enabled, this will automatically setup your webhook's CA to the one used + # by cert-manager. See https://cert-manager.io/docs/concepts/ca-injector + addInjectorAnnotations: true + cert: + # -- Create a certificate resource within this chart. See + # https://cert-manager.io/docs/usage/certificate/ + create: true + # -- For the Certificate created by this chart, setup the issuer. See + # https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.IssuerSpec + issuerRef: + group: cert-manager.io + kind: "Issuer" + name: "my-issuer" + # -- Set the requested duration (i.e. lifetime) of the Certificate. See + # https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec + # One year by default. + duration: "8760h" + # -- How long before the currently issued certificate’s expiry + # cert-manager should renew the certificate. See + # https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec + # Note that renewBefore should be greater than .webhook.lookaheadInterval + # since the webhook will check this far in advance that the certificate is + # valid. + renewBefore: "" + # -- Add extra annotations to the Certificate resource. + annotations: {} + + tolerations: [] + + topologySpreadConstraints: [] + + affinity: {} + + # -- Pod priority class name. + priorityClassName: "" + + # -- Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1 + + metrics: + + listen: + port: 8080 + + service: + # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics + enabled: false + + # -- Metrics service port to scrape + port: 8080 + + # -- Additional service annotations + annotations: {} + + + readinessProbe: + # -- Address for readiness probe + address: "" + # -- ReadinessProbe port for kubelet + port: 8081 + + + ## -- Extra environment variables to add to container. + extraEnv: [] + + ## -- Map of extra arguments to pass to container. + extraArgs: {} + + ## -- Extra volumes to pass to pod. + extraVolumes: [] + + ## -- Extra volumes to mount to the container. + extraVolumeMounts: [] + + # -- Annotations to add to Secret + secretAnnotations: {} + + # -- Annotations to add to Deployment + deploymentAnnotations: {} + + # -- Annotations to add to Pod + podAnnotations: {} + + podLabels: {} + + podSecurityContext: + enabled: true + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + enabled: true + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + +certController: + # -- Specifies whether a certificate controller deployment be created. + create: true + requeueInterval: "5m" + replicaCount: 1 + # -- Specifices Log Params to the Webhook + log: + level: info + timeEncoding: epoch + # -- Specifies the amount of historic ReplicaSets k8s should keep (see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy) + revisionHistoryLimit: 10 + + image: + repository: ghcr.io/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "" + flavour: "" + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + rbac: + # -- Specifies whether role and rolebinding resources should be created. + create: true + serviceAccount: + # -- Specifies whether a service account should be created. + create: true + # -- Automounts the service account token in all containers of the pod + automount: true + # -- Annotations to add to the service account. + annotations: {} + # -- Extra Labels to add to the service account. + extraLabels: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + nodeSelector: {} + + tolerations: [] + + topologySpreadConstraints: [] + + affinity: {} + + # -- Run the certController on the host network + hostNetwork: false + + # -- Pod priority class name. + priorityClassName: "" + + # -- Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1 + + metrics: + + listen: + port: 8080 + + service: + # -- Enable if you use another monitoring tool than Prometheus to scrape the metrics + enabled: false + + # -- Metrics service port to scrape + port: 8080 + + # -- Additional service annotations + annotations: {} + + readinessProbe: + # -- Address for readiness probe + address: "" + # -- ReadinessProbe port for kubelet + port: 8081 + + ## -- Extra environment variables to add to container. + extraEnv: [] + + ## -- Map of extra arguments to pass to container. + extraArgs: {} + + + ## -- Extra volumes to pass to pod. + extraVolumes: [] + + ## -- Extra volumes to mount to the container. + extraVolumeMounts: [] + + # -- Annotations to add to Deployment + deploymentAnnotations: {} + + # -- Annotations to add to Pod + podAnnotations: {} + + podLabels: {} + + podSecurityContext: + enabled: true + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + enabled: true + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + +# -- Specifies `dnsPolicy` to deployment +dnsPolicy: ClusterFirst + +# -- Specifies `dnsOptions` to deployment +dnsConfig: {} + +# -- Any extra pod spec on the deployment +podSpecExtra: {} diff --git a/index.yaml b/index.yaml index 67bce00f2..58514124e 100644 --- a/index.yaml +++ b/index.yaml @@ -4039,6 +4039,38 @@ entries: - assets/cerbos/cerbos-0.37.0.tgz version: 0.37.0 cf-runtime: + - annotations: + artifacthub.io/changes: | + - kind: fixed + description: "Handling of image signing with certificate and private key password" + artifacthub.io/containsSecurityUpdates: "false" + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Codefresh + catalog.cattle.io/kube-version: '>=1.18-0' + catalog.cattle.io/release-name: cf-runtime + apiVersion: v2 + created: "2024-09-10T00:52:06.167016079Z" + dependencies: + - name: cf-common + repository: file://./charts/cf-common + version: 0.16.0 + description: A Helm chart for Codefresh Runner + digest: f1015c3ff808be796e7d28103e072ec8ba2f2f0007909440bddb2744b8efbf84 + home: https://codefresh.io/ + icon: file://assets/icons/cf-runtime.png + keywords: + - codefresh + - runner + kubeVersion: '>=1.18-0' + maintainers: + - name: codefresh + url: https://codefresh-io.github.io/ + name: cf-runtime + sources: + - https://github.com/codefresh-io/venona + urls: + - assets/codefresh/cf-runtime-6.3.58.tgz + version: 6.3.58 - annotations: artifacthub.io/changes: | - kind: fixed @@ -5106,6 +5138,28 @@ entries: - assets/cloudcasa/cloudcasa-3.4.1.tgz version: 3.4.1 cockroachdb: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: CockroachDB + catalog.cattle.io/kube-version: '>=1.8-0' + catalog.cattle.io/release-name: cockroachdb + apiVersion: v1 + appVersion: 24.2.1 + created: "2024-09-10T00:52:06.141565829Z" + description: CockroachDB is a scalable, survivable, strongly-consistent SQL database. + digest: 52d7756a56b977f6722d7364bcdc8eb417a001ddbacbb1e00878846179b9715c + home: https://www.cockroachlabs.com + icon: file://assets/icons/cockroachdb.png + kubeVersion: '>=1.8-0' + maintainers: + - email: helm-charts@cockroachlabs.com + name: cockroachlabs + name: cockroachdb + sources: + - https://github.com/cockroachdb/cockroach + urls: + - assets/cockroach-labs/cockroachdb-14.0.1.tgz + version: 14.0.1 - annotations: catalog.cattle.io/certified: partner catalog.cattle.io/display-name: CockroachDB @@ -10000,6 +10054,35 @@ entries: - assets/dynatrace/dynatrace-operator-0.12.0.tgz version: 0.12.0 external-secrets: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: External Secrets Operator + catalog.cattle.io/kube-version: '>= 1.19.0-0' + catalog.cattle.io/release-name: external-secrets + apiVersion: v2 + appVersion: v0.10.3 + created: "2024-09-10T00:52:06.382488304Z" + dependencies: + - condition: bitwarden-sdk-server.enabled + name: bitwarden-sdk-server + repository: file://./charts/bitwarden-sdk-server + version: v0.3.1 + description: External secret management for Kubernetes + digest: 082bed3717b8e4482c7d78f329decb8fa56f5e3afb7ddadc4cb48ca5f10293bb + home: https://github.com/external-secrets/external-secrets + icon: file://assets/icons/external-secrets.png + keywords: + - kubernetes-external-secrets + - secrets + kubeVersion: '>= 1.19.0-0' + maintainers: + - email: kellinmcavoy@gmail.com + name: mcavoyk + name: external-secrets + type: application + urls: + - assets/external-secrets/external-secrets-0.10.3.tgz + version: 0.10.3 - annotations: catalog.cattle.io/certified: partner catalog.cattle.io/display-name: External Secrets Operator @@ -41947,4 +42030,4 @@ entries: urls: - assets/netfoundry/ziti-host-1.5.1.tgz version: 1.5.1 -generated: "2024-09-07T00:50:00.028083031Z" +generated: "2024-09-10T00:52:05.778030849Z"