diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f3dcf9d5..23610128 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -63,7 +63,7 @@ jobs: - id: 'set-up-chart-testing' name: Install Chart Testing CLI - uses: 'helm/chart-testing-action@v2.4.0' + uses: 'helm/chart-testing-action@v2.6.1' with: version: 'v3.8.0' @@ -95,34 +95,66 @@ jobs: - id: 'test' name: Run Go Tests - run: 'go test ./...' + run: 'go test -p 1 ./...' if: steps.list-changed.outputs.changed == 'true' - id: 'zitadel-test-namespaces' name: Grep Created Namespaces run: | - echo "inlineSecretsNamespace=$(kubectl get namespaces --output name | grep 1-inline-secrets | cut -d / -f 2)" >> "$GITHUB_OUTPUT" - echo "refSecretsNamespace=$(kubectl get namespaces --output name | grep 2-ref-secrets | cut -d / -f 2)" >> "$GITHUB_OUTPUT" - echo "machineKeyNamespace=$(kubectl get namespaces --output name | grep 3-machine-key | cut -d / -f 2)" >> "$GITHUB_OUTPUT" + echo "pgInsecure=$(kubectl get namespaces --output name | grep 1-postgres-insecure | cut -d / -f 2)" >> "$GITHUB_OUTPUT" + echo "pgSecure=$(kubectl get namespaces --output name | grep 2-postgres-secure | cut -d / -f 2)" >> "$GITHUB_OUTPUT" + echo "crInsecure=$(kubectl get namespaces --output name | grep 3-cockroach-insecure | cut -d / -f 2)" >> "$GITHUB_OUTPUT" + echo "crSecure=$(kubectl get namespaces --output name | grep 4-cockroach-secure | cut -d / -f 2)" >> "$GITHUB_OUTPUT" + echo "refSecrets=$(kubectl get namespaces --output name | grep 5-referenced-secrets | cut -d / -f 2)" >> "$GITHUB_OUTPUT" + echo "machineUser=$(kubectl get namespaces --output name | grep 6-machine-user | cut -d / -f 2)" >> "$GITHUB_OUTPUT" + echo "selfSigned=$(kubectl get namespaces --output name | grep 7-self-signed | cut -d / -f 2)" >> "$GITHUB_OUTPUT" if: always() - - id: 'namespace-report-inline-secrets' - name: Show Inline Secrets Namespace + - id: 'namespace-report-pg-insecure' + name: Show ${{ steps.zitadel-test-namespaces.outputs.pgInsecure }} Namespace uses: jupyterhub/action-k8s-namespace-report@v1 if: always() with: - namespace: ${{ steps.zitadel-test-namespaces.outputs.inlineSecretsNamespace }} + namespace: ${{ steps.zitadel-test-namespaces.outputs.pgInsecure }} + + - id: 'namespace-report-pg-secure' + name: Show ${{ steps.zitadel-test-namespaces.outputs.pgSecure }} Namespace + uses: jupyterhub/action-k8s-namespace-report@v1 + if: always() + with: + namespace: ${{ steps.zitadel-test-namespaces.outputs.pgSecure }} + + - id: 'namespace-report-cr-insecure' + name: Show ${{ steps.zitadel-test-namespaces.outputs.crInsecure }} Namespace + uses: jupyterhub/action-k8s-namespace-report@v1 + if: always() + with: + namespace: ${{ steps.zitadel-test-namespaces.outputs.crInsecure }} + + - id: 'namespace-report-cr-secure' + name: Show ${{ steps.zitadel-test-namespaces.outputs.crSecure }} Namespace + uses: jupyterhub/action-k8s-namespace-report@v1 + if: always() + with: + namespace: ${{ steps.zitadel-test-namespaces.outputs.crSecure }} - id: 'namespace-report-ref-secrets' - name: Show Referenced Secrets Namespace + name: Show ${{ steps.zitadel-test-namespaces.outputs.refSecrets }} Namespace + uses: jupyterhub/action-k8s-namespace-report@v1 + if: always() + with: + namespace: ${{ steps.zitadel-test-namespaces.outputs.refSecrets }} + + - id: 'namespace-report-machine-user' + name: Show ${{ steps.zitadel-test-namespaces.outputs.machineUser }} Namespace uses: jupyterhub/action-k8s-namespace-report@v1 if: always() with: - namespace: ${{ steps.zitadel-test-namespaces.outputs.refSecretsNamespace }} + namespace: ${{ steps.zitadel-test-namespaces.outputs.machineUser }} - - id: 'namespace-report-machine-key' - name: Show Machine Key Namespace + - id: 'namespace-report-self-signed' + name: Show ${{ steps.zitadel-test-namespaces.outputs.selfSigned }} Namespace uses: jupyterhub/action-k8s-namespace-report@v1 if: always() with: - namespace: ${{ steps.zitadel-test-namespaces.outputs.machineKeyNamespace }} + namespace: ${{ steps.zitadel-test-namespaces.outputs.selfSigned }} diff --git a/charts/zitadel/Chart.yaml b/charts/zitadel/Chart.yaml index bd265b54..d93462ed 100644 --- a/charts/zitadel/Chart.yaml +++ b/charts/zitadel/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: zitadel description: A Helm chart for ZITADEL type: application -appVersion: "v2.35.0" -version: 7.1.0 +appVersion: "v2.41.0" +version: 7.2.0 kubeVersion: ">= 1.21.0-0" icon: https://zitadel.com/zitadel-logo-dark.svg maintainers: diff --git a/charts/zitadel/acceptance/acceptance_test.go b/charts/zitadel/acceptance/acceptance_test.go index dbb85a2d..df7a5843 100644 --- a/charts/zitadel/acceptance/acceptance_test.go +++ b/charts/zitadel/acceptance/acceptance_test.go @@ -14,13 +14,16 @@ import ( func TestPostgresInsecure(t *testing.T) { t.Parallel() example := "1-postgres-insecure" - workDir, values := workingDirectory(example) + workDir, valuesFile, values := readConfig(t, example) + cfg := values.Zitadel.ConfigmapConfig suite.Run(t, acceptance.Configure( t, newNamespaceIdentifier(example), acceptance.Postgres.WithValues(filepath.Join(workDir, "postgres-values.yaml")), - []string{values}, - "", + []string{valuesFile}, + cfg.ExternalDomain, + cfg.ExternalPort, + cfg.ExternalSecure, nil, nil, nil, @@ -30,13 +33,16 @@ func TestPostgresInsecure(t *testing.T) { func TestPostgresSecure(t *testing.T) { t.Parallel() example := "2-postgres-secure" - workDir, values := workingDirectory(example) + workDir, valuesFile, values := readConfig(t, example) + cfg := values.Zitadel.ConfigmapConfig suite.Run(t, acceptance.Configure( t, newNamespaceIdentifier(example), acceptance.Postgres.WithValues(filepath.Join(workDir, "postgres-values.yaml")), - []string{values}, - "", + []string{valuesFile}, + cfg.ExternalDomain, + cfg.ExternalPort, + cfg.ExternalSecure, func(cfg *acceptance.ConfigurationTest) { k8s.KubectlApply(t, cfg.KubeOptions, filepath.Join(workDir, "certs-job.yaml")) k8s.WaitUntilJobSucceed(t, cfg.KubeOptions, "create-certs", 120, 3*time.Second) @@ -49,13 +55,16 @@ func TestPostgresSecure(t *testing.T) { func TestCockroachInsecure(t *testing.T) { t.Parallel() example := "3-cockroach-insecure" - workDir, values := workingDirectory(example) + workDir, valuesFile, values := readConfig(t, example) + cfg := values.Zitadel.ConfigmapConfig suite.Run(t, acceptance.Configure( t, newNamespaceIdentifier(example), acceptance.Cockroach.WithValues(filepath.Join(workDir, "cockroach-values.yaml")), - []string{values}, - "", + []string{valuesFile}, + cfg.ExternalDomain, + cfg.ExternalPort, + cfg.ExternalSecure, nil, nil, nil, @@ -65,13 +74,16 @@ func TestCockroachInsecure(t *testing.T) { func TestCockroachSecure(t *testing.T) { t.Parallel() example := "4-cockroach-secure" - workDir, values := workingDirectory(example) + workDir, valuesFile, values := readConfig(t, example) + cfg := values.Zitadel.ConfigmapConfig suite.Run(t, acceptance.Configure( t, newNamespaceIdentifier(example), acceptance.Cockroach.WithValues(filepath.Join(workDir, "cockroach-values.yaml")), - []string{values}, - "", + []string{valuesFile}, + cfg.ExternalDomain, + cfg.ExternalPort, + cfg.ExternalSecure, nil, func(cfg *acceptance.ConfigurationTest) { k8s.KubectlApply(t, cfg.KubeOptions, filepath.Join(workDir, "zitadel-cert-job.yaml")) @@ -84,13 +96,16 @@ func TestCockroachSecure(t *testing.T) { func TestReferencedSecrets(t *testing.T) { t.Parallel() example := "5-referenced-secrets" - workDir, values := workingDirectory(example) + workDir, valuesFile, values := readConfig(t, example) + cfg := values.Zitadel.ConfigmapConfig suite.Run(t, acceptance.Configure( t, newNamespaceIdentifier(example), acceptance.Postgres.WithValues(filepath.Join(workDir, "postgres-values.yaml")), - []string{values}, - "", + []string{valuesFile}, + cfg.ExternalDomain, + cfg.ExternalPort, + cfg.ExternalSecure, nil, func(cfg *acceptance.ConfigurationTest) { k8s.KubectlApply(t, cfg.KubeOptions, filepath.Join(workDir, "zitadel-secrets.yaml")) @@ -103,16 +118,38 @@ func TestReferencedSecrets(t *testing.T) { func TestMachineUser(t *testing.T) { t.Parallel() example := "6-machine-user" - workDir, values := workingDirectory(example) - saUserame := readValues(t, values).Zitadel.ConfigmapConfig.FirstInstance.Org.Machine.Machine.Username + workDir, valuesFile, values := readConfig(t, example) + cfg := values.Zitadel.ConfigmapConfig + saUsername := cfg.FirstInstance.Org.Machine.Machine.Username suite.Run(t, acceptance.Configure( t, newNamespaceIdentifier(example), acceptance.Postgres.WithValues(filepath.Join(workDir, "postgres-values.yaml")), - []string{values}, - "", + []string{valuesFile}, + cfg.ExternalDomain, + cfg.ExternalPort, + cfg.ExternalSecure, nil, nil, - testAuthenticatedAPI(saUserame, fmt.Sprintf("%s.json", saUserame))), + testAuthenticatedAPI(saUsername, fmt.Sprintf("%s.json", saUsername))), ) } + +func TestSelfSigned(t *testing.T) { + t.Parallel() + example := "7-self-signed" + workDir, valuesFile, values := readConfig(t, example) + cfg := values.Zitadel.ConfigmapConfig + suite.Run(t, acceptance.Configure( + t, + newNamespaceIdentifier(example), + acceptance.Postgres.WithValues(filepath.Join(workDir, "postgres-values.yaml")), + []string{valuesFile}, + cfg.ExternalDomain, + cfg.ExternalPort, + cfg.ExternalSecure, + nil, + nil, + nil, + )) +} diff --git a/charts/zitadel/acceptance/accessibility.go b/charts/zitadel/acceptance/accessibility.go index 808ef4d2..128f3fda 100644 --- a/charts/zitadel/acceptance/accessibility.go +++ b/charts/zitadel/acceptance/accessibility.go @@ -2,9 +2,12 @@ package acceptance import ( "context" + "crypto/x509" + "errors" "fmt" mgmt_api "github.com/zitadel/zitadel-go/v2/pkg/client/zitadel/management" "net/http" + "strconv" "strings" "sync" "time" @@ -75,6 +78,10 @@ func (s *ConfigurationTest) checkAccessibility(pods []corev1.Pod) { checkOptionsFunc(func(ctx context.Context) error { randomInvalidKey := `{"type":"serviceaccount","keyId":"229185755715993707","key":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAm8bpVfzWJuZsEz1VfTrwSAdkbH+i/u2NS4dv60lwIjtXzrU7\n1xZkHw9jxqz+c+APTaTzp1KY49Dc/wcwXv032FuD1GK2ZSRnMaHm8QnNt8Xhi0e8\nBlu3QQmlqxWPCI67wDPUwXoSHM+r9gQXn2pOR0oonoLP+Gzef+RRj1zUFpZmHWPX\nxw4UWWHwl4xChw9iyO4HbZZGe6wBVYVWe2BnvviCVEeKapyjaCqokZES38S4+S2X\nit202xLlRDyXs3XFWmBzHGmEsxx3LZZor85Kbph/bGjDcV8rdQC1YKC++z8OhuLp\n79GltP7YWrfMN3Z8iRUJQY9APrKQYtljVkWrnQIDAQABAoIBAQCIRZrLyRHCF+LF\ndes6UPvv1t+n9oQtRLxNLV7f0m+Q0p7+yhZeE01kyn67R4yU65YXk0w+vIfZC1a4\nlp5fCl73Gx+ZBP2QPyczCPHRPIVE1Yt33zoByevmrjzKDGMC1nIyMmVVF6eOorFI\n1s2ffEycGqir+b1bEkoWUTJ0Gn3Cf1PE4vTgenHhCrYSvMsbmszQ5GDlfxNj27qf\nF2YrnLx11GplMYU0YEzGqSQHxw76rrmF7yiTvbB+olsjXWARAJxBriSlrF2BDYQk\n+HJ8MEwhWhncaZH1i0Xz/jarDBizpo2o1+K1ZqF6RBUknT72EPnMxI9JsvS4FH44\nZfbrujBhAoGBAMQnx6tO79GpnBIAr7iELyUu5F4mCdU6D0rOAiCjXPpCUAdCDuwX\nzROonIGXPPmhzXXtxebeTz4cf+P8p6tUnrqpl/f0Oi1DMOzv0jL/SAUDC9uUrg6k\nurXZT2dgeONwd1pADyNXSpbZfwRE5IoecFg6cgFi4kune0mdG3mr8QjpAoGBAMtN\nerrMc+4bc3GsmWG4FSXn3xlWMeVGIo2/owP2P5MuMu0ibjofZkl28y0xo8dJgWmv\nLiFSEOhUy+TXZK7K1a2+fD+AXHHaHkBjNbTmCaAbf7rZnuUL4iZVpQyIoTCVuAwo\nC6bsE4TcwGddk4yZj/WZ7v1be+uNgeYwQr2UshyVAoGAN8pYsBCzhR6IlVY8pG50\nOk8sBNss0MjCsLQHRuEwAL37pRTUybG7UmwSl4k8foPWvEP0lcWFJFVWyrGBvulC\nfDTgVFXSdi02LS3Iy1hwU3yaUsnm96NCt5YnT2/Q8l96kuDFbXfWbzFNPxmZJu+h\nZHa7FknZs0rfdgCJYAHXfIECgYEAw3kSqSrNyMICJOkkbO2W/+RLAUx8GwttS8dX\nkQaip/wCoTi6rQ3lxnslY23YIFRPpvL1srn6YbiudrCXMOz7uNtvEYt01082SQha\n6j1IQfZOwLRfb7EWV29/i2aPPWynEqEqWuuf9N5f7MLvjH9WCHpibJ4aryhXHqGG\nekvPWWUCgYA5qDsPk5ykRWEALbunzB/RkpxR6LTLSwriU/OzRswOiKo8UPqH4JZI\nOsFAgudG5H+UOEGMuaSvIq0PLbGex16PjKqUsRwgIoPdH8183f9fxZSJDmr7ELIy\nZJEvE3eJnYwMOpSEZS0VR5Sw0CmKV2Hhd+u6rRB8YjXMP0nAVg8eOA==\n-----END RSA PRIVATE KEY-----\n","userId":"229185755715600491"}` conn, err := OpenGRPCConnection(s, []byte(randomInvalidKey)) + if errors.As(err, &x509.UnknownAuthorityError{}) { + // The gRPC client doesn't support skipping the server cert validation + return nil + } if err != nil { return fmt.Errorf("couldn't create gRPC management client: %w", err) } @@ -87,12 +94,14 @@ func (s *ConfigurationTest) checkAccessibility(pods []corev1.Pod) { })) for i := range pods { pod := pods[i] - port := 8081 + i - - podTunnel := k8s.NewTunnel(s.KubeOptions, k8s.ResourceTypePod, pod.Name, port, 8080) + podTunnel := k8s.NewTunnel(s.KubeOptions, k8s.ResourceTypePod, pod.Name, 0, 8080) podTunnel.ForwardPort(s.T()) tunnels = append(tunnels, podTunnel) - checks = append(checks, zitadelStatusChecks(s.Scheme, s.Domain, uint16(port))...) + localPort, err := strconv.ParseUint(strings.Split(podTunnel.Endpoint(), ":")[1], 10, 16) + if err != nil { + s.T().Fatal(err) + } + checks = append(checks, zitadelStatusChecks(s.Scheme, s.Domain, uint16(localPort))...) } wg := sync.WaitGroup{} for _, check := range checks { diff --git a/charts/zitadel/acceptance/await.go b/charts/zitadel/acceptance/await.go index 1a91a816..dbe6383a 100644 --- a/charts/zitadel/acceptance/await.go +++ b/charts/zitadel/acceptance/await.go @@ -18,6 +18,7 @@ func Await(ctx context.Context, t *testing.T, wg *sync.WaitGroup, tries int, cb if tries == 0 { t.Fatal(err) } + t.Logf("got error %v. trying again in a second", err) time.Sleep(time.Second) Await(ctx, t, wg, tries-1, cb) } diff --git a/charts/zitadel/acceptance/config.go b/charts/zitadel/acceptance/config.go index b79ce239..7dea6dc8 100644 --- a/charts/zitadel/acceptance/config.go +++ b/charts/zitadel/acceptance/config.go @@ -67,6 +67,8 @@ func Configure( dbChart databaseChart, zitadelValues []string, externalDomain string, + externalPort uint16, + externalSecure bool, before, afterDB, afterZITADEL hookFunc, ) *ConfigurationTest { chartPath, err := filepath.Abs("..") @@ -77,9 +79,9 @@ func Configure( if err != nil { t.Fatal(err) } - domain := "localhost" - if externalDomain != "" { - domain = externalDomain + externalScheme := "http" + if externalSecure { + externalScheme = "https" } cfg := &ConfigurationTest{ Ctx: context.Background(), @@ -95,9 +97,9 @@ func Configure( beforeFunc: before, afterDBFunc: afterDB, afterZITADELFunc: afterZITADEL, - Domain: domain, - Port: 8080, - Scheme: "http", + Domain: externalDomain, + Port: externalPort, + Scheme: externalScheme, } cfg.SetT(t) return cfg diff --git a/charts/zitadel/acceptance/config_test.go b/charts/zitadel/acceptance/config_test.go index 949dea2b..c15d9838 100644 --- a/charts/zitadel/acceptance/config_test.go +++ b/charts/zitadel/acceptance/config_test.go @@ -11,12 +11,15 @@ import ( "testing" ) -func readValues(t *testing.T, valuesFilePath string) (values struct { +type Values struct { Zitadel struct { MasterkeySecretName string `yaml:"masterkeySecretName"` ConfigSecretName string `yaml:"configSecretName"` ConfigmapConfig struct { - FirstInstance struct { + ExternalDomain string `yaml:"ExternalDomain"` + ExternalPort uint16 `yaml:"ExternalPort"` + ExternalSecure bool `yaml:"ExternalSecure"` + FirstInstance struct { Org struct { Machine struct { Machine struct { @@ -27,7 +30,13 @@ func readValues(t *testing.T, valuesFilePath string) (values struct { } `yaml:"FirstInstance"` } `yaml:"configmapConfig"` } `yaml:"zitadel"` -}) { +} + +func readValues(t *testing.T, valuesFilePath string) (values Values) { + // set default values like in the defaults.yaml + values.Zitadel.ConfigmapConfig.ExternalDomain = "localhost" + values.Zitadel.ConfigmapConfig.ExternalPort = 8080 + values.Zitadel.ConfigmapConfig.ExternalSecure = true valuesBytes, err := os.ReadFile(valuesFilePath) if err != nil { t.Fatal(err) @@ -65,3 +74,8 @@ func workingDirectory(exampleDir string) (workingDir, valuesFile string) { valuesFile = filepath.Join(workingDir, "zitadel-values.yaml") return workingDir, valuesFile } + +func readConfig(t *testing.T, exampleDir string) (string, string, Values) { + workingDir, valuesFile := workingDirectory(exampleDir) + return workingDir, valuesFile, readValues(t, valuesFile) +} diff --git a/charts/zitadel/acceptance/request.go b/charts/zitadel/acceptance/request.go index 2ff40401..e9ae9aec 100644 --- a/charts/zitadel/acceptance/request.go +++ b/charts/zitadel/acceptance/request.go @@ -2,6 +2,7 @@ package acceptance import ( "context" + "crypto/tls" "fmt" "io" "net/http" @@ -23,7 +24,8 @@ func httpCall(ctx context.Context, method string, url string, beforeSend func(re if beforeSend != nil { beforeSend(req) } - resp, err := http.DefaultClient.Do(req) + httpClient := http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}} + resp, err := httpClient.Do(req) if err != nil { return nil, nil, fmt.Errorf("sending request %+v failed: %s", *req, err) } diff --git a/charts/zitadel/acceptance/run.go b/charts/zitadel/acceptance/run.go index c60b2226..8934e208 100644 --- a/charts/zitadel/acceptance/run.go +++ b/charts/zitadel/acceptance/run.go @@ -15,9 +15,8 @@ func (s *ConfigurationTest) TestZITADELInstallation() { KubectlOptions: s.KubeOptions, ValuesFiles: s.zitadelValues, SetValues: map[string]string{ - "replicaCount": "1", - "pdb.enabled": "true", - "ingress.enabled": "true", + "replicaCount": "1", + "pdb.enabled": "true", }, }, s.zitadelChartPath, s.zitadelRelease) k8s.WaitUntilJobSucceed(s.T(), s.KubeOptions, "zitadel-test-init", 900, time.Second) diff --git a/charts/zitadel/acceptance/service_tunnel.go b/charts/zitadel/acceptance/service_tunnel.go index f54efbc3..5d894757 100644 --- a/charts/zitadel/acceptance/service_tunnel.go +++ b/charts/zitadel/acceptance/service_tunnel.go @@ -15,19 +15,19 @@ func (c CloseFunc) Close() { // ServiceTunnel must be closed using the returned close function func ServiceTunnel(cfg *ConfigurationTest) func() { - serviceTunnel := k8s.NewTunnel(cfg.KubeOptions, k8s.ResourceTypeService, cfg.zitadelRelease, 8080, 8080) - awaitPortToBeFree(cfg, 8080) + serviceTunnel := k8s.NewTunnel(cfg.KubeOptions, k8s.ResourceTypeService, cfg.zitadelRelease, int(cfg.Port), 8080) + awaitServicePortToBeFree(cfg) serviceTunnel.ForwardPort(cfg.T()) return serviceTunnel.Close } -func awaitPortToBeFree(cfg *ConfigurationTest, port int) { +func awaitServicePortToBeFree(cfg *ConfigurationTest) { t := cfg.T() - addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", cfg.Port)) if err != nil { t.Fatal(err) } - Await(cfg.Ctx, t, nil, 60, func(ctx context.Context) error { + Await(cfg.Ctx, t, nil, 300, func(ctx context.Context) error { l, err := net.ListenTCP("tcp", addr) if err != nil { return err diff --git a/charts/zitadel/acceptance/teardown.go b/charts/zitadel/acceptance/teardown.go index 18105354..14303d7b 100644 --- a/charts/zitadel/acceptance/teardown.go +++ b/charts/zitadel/acceptance/teardown.go @@ -1,16 +1,10 @@ package acceptance import ( - "os" - "github.com/gruntwork-io/terratest/modules/k8s" ) func (s *ConfigurationTest) TearDownTest() { - if _, exists := os.LookupEnv("GITHUB_SHA"); exists { - s.log.Logf(s.T(), "Not running cleanup tasks, as tests were run on a throwaway runner") - return - } if !s.T().Failed() { k8s.DeleteNamespace(s.T(), s.KubeOptions, s.KubeOptions.Namespace) } else { diff --git a/charts/zitadel/templates/deployment.yaml b/charts/zitadel/templates/deployment.yaml index 05f2b1c5..aab1a4cd 100644 --- a/charts/zitadel/templates/deployment.yaml +++ b/charts/zitadel/templates/deployment.yaml @@ -65,13 +65,19 @@ spec: {{- if (or .Values.zitadel.dbSslCaCrt .Values.zitadel.dbSslCaCrtSecret) }} - name: ZITADEL_DATABASE_{{ $dbEnv }}_USER_SSL_ROOTCERT value: /.secrets/db-ssl-ca-crt/ca.crt - {{- end}} + {{- end }} {{- if .Values.zitadel.dbSslUserCrtSecret }} - name: ZITADEL_DATABASE_{{ $dbEnv }}_USER_SSL_CERT value: /.secrets/db-ssl-user-crt/tls.crt - name: ZITADEL_DATABASE_{{ $dbEnv }}_USER_SSL_KEY value: /.secrets/db-ssl-user-crt/tls.key - {{- end}} + {{- end }} + {{- if .Values.zitadel.selfSignedCert.enabled }} + - name: ZITADEL_TLS_CERTPATH + value: /etc/tls/tls.crt + - name: ZITADEL_TLS_KEYPATH + value: /etc/tls/tls.key + {{- end }} {{- with .Values.env }} {{- toYaml . | nindent 12 }} {{- end }} @@ -125,6 +131,10 @@ spec: mountPath: /config - name: chowned-secrets mountPath: /.secrets + {{- if .Values.zitadel.selfSignedCert.enabled }} + - name: tls + mountPath: /etc/tls + {{- end }} resources: {{- toYaml .Values.resources | nindent 14 }} initContainers: @@ -163,6 +173,31 @@ spec: securityContext: runAsNonRoot: false runAsUser: 0 + {{- if .Values.zitadel.selfSignedCert.enabled }} + - name: generate-self-signed-cert + image: alpine/openssl + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + volumeMounts: + - name: tls + mountPath: "/etc/tls" + command: + - "/bin/ash" + - "-c" + - "openssl req -nodes -x509 -sha256 -newkey rsa:4096 -keyout /etc/tls/tls.key -out /etc/tls/tls.crt -days 3560 -subj \"/CN=ZITADEL Chart Demo\" -addext \"subjectAltName = DNS:localhost,DNS:${POD_IP},DNS:${POD_NAME}{{- if .Values.zitadel.configmapConfig.ExternalDomain -}},DNS:{{- .Values.zitadel.configmapConfig.ExternalDomain -}}{{- end -}}{{- if .Values.zitadel.selfSignedCert.additionalDnsName -}},DNS:{{- .Values.zitadel.selfSignedCert.additionalDnsName -}}{{- end -}}\"" + securityContext: + readOnlyRootFilesystem: true + runAsNonRoot: true + privileged: false + runAsUser: 1000 + {{- end }} volumes: - name: zitadel-config-yaml configMap: @@ -194,6 +229,10 @@ spec: {{- end }} - name: chowned-secrets emptyDir: {} + {{- if .Values.zitadel.selfSignedCert.enabled }} + - name: tls + emptyDir: {} + {{- end }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/charts/zitadel/values.yaml b/charts/zitadel/values.yaml index 8db52f6b..81f2c005 100644 --- a/charts/zitadel/values.yaml +++ b/charts/zitadel/values.yaml @@ -4,6 +4,7 @@ zitadel: # See all defaults here: # https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml configmapConfig: + ExternalSecure: true Machine: Identification: Hostname: @@ -40,6 +41,14 @@ zitadel: # The db users secret containing the client certificate and key at tls.crt and tls.key needed for establishing secure database connections dbSslUserCrtSecret: "" + # Generate a self-signed certificate using an init container + # This will also mount the generated files to /etc/tls/ so that you can reference them in the pod. + # E.G. KeyPath: /etc/tls/tls.key CertPath: /etc/tls/tls.crt + # By default, the SAN DNS names include, localhost, the POD IP address and the POD name. You may include one more by using additionalDnsName like "my.zitadel.fqdn". + selfSignedCert: + enabled: false + additionalDnsName: + replicaCount: 3 image: diff --git a/examples/1-postgres-insecure/README.md b/examples/1-postgres-insecure/README.md index 9d75eaf1..ebb17fbc 100644 --- a/examples/1-postgres-insecure/README.md +++ b/examples/1-postgres-insecure/README.md @@ -24,7 +24,7 @@ When ZITADEL is ready, you can access the GUI via port-forwarding: kubectl port-forward svc/my-zitadel 8080 ``` -Now, open http://localhost:8080 in your browser and log in with the following credentials: +Now, open http://127.0.0.1.sslip.io:8080 in your browser and log in with the following credentials: -**Username**: zitadel-admin@zitadel.localhost +**Username**: zitadel-admin@zitadel.127.0.0.1.sslip.io **Password**: Password1! diff --git a/examples/1-postgres-insecure/zitadel-values.yaml b/examples/1-postgres-insecure/zitadel-values.yaml index 799fb40f..a84c0d6a 100644 --- a/examples/1-postgres-insecure/zitadel-values.yaml +++ b/examples/1-postgres-insecure/zitadel-values.yaml @@ -2,7 +2,7 @@ zitadel: masterkey: x123456789012345678901234567891y configmapConfig: ExternalSecure: false - ExternalDomain: localhost + ExternalDomain: 127.0.0.1.sslip.io TLS: Enabled: false Database: diff --git a/examples/2-postgres-secure/README.md b/examples/2-postgres-secure/README.md index b96be417..82fe38f3 100644 --- a/examples/2-postgres-secure/README.md +++ b/examples/2-postgres-secure/README.md @@ -24,7 +24,7 @@ When ZITADEL is ready, you can access the GUI via port-forwarding: kubectl port-forward svc/my-zitadel 8080 ``` -Now, open http://localhost:8080 in your browser and log in with the following credentials: +Now, open http://127.0.0.1.sslip.io:8080 in your browser and log in with the following credentials: -**Username**: zitadel-admin@zitadel.localhost +**Username**: zitadel-admin@zitadel.127.0.0.1.sslip.io **Password**: Password1! diff --git a/examples/2-postgres-secure/zitadel-values.yaml b/examples/2-postgres-secure/zitadel-values.yaml index 4923de4d..e5989e67 100644 --- a/examples/2-postgres-secure/zitadel-values.yaml +++ b/examples/2-postgres-secure/zitadel-values.yaml @@ -2,7 +2,7 @@ zitadel: masterkey: x123456789012345678901234567891y configmapConfig: ExternalSecure: false - ExternalDomain: localhost + ExternalDomain: 127.0.0.1.sslip.io TLS: Enabled: false Database: diff --git a/examples/3-cockroach-insecure/README.md b/examples/3-cockroach-insecure/README.md index 2dcb6c3e..62f15713 100644 --- a/examples/3-cockroach-insecure/README.md +++ b/examples/3-cockroach-insecure/README.md @@ -11,7 +11,7 @@ Also, you deploy [a correctly configured ZITADEL](https://artifacthub.io/package ```bash # Install Cockroach helm repo add cockroachdb https://charts.cockroachdb.com/ -helm install --wait db cockroachdb/cockroachdb --version 11.1.5 --values https://raw.githubusercontent.com/zitadel/zitadel-charts/main/examples/3-cocroach-insecure/cockroach-values.yaml +helm install --wait db cockroachdb/cockroachdb --version 11.2.1 --values https://raw.githubusercontent.com/zitadel/zitadel-charts/main/examples/3-cocroach-insecure/cockroach-values.yaml # Install ZITADEL helm repo add zitadel https://charts.zitadel.com @@ -24,7 +24,7 @@ When ZITADEL is ready, you can access the GUI via port-forwarding: kubectl port-forward svc/my-zitadel 8080 ``` -Now, open http://localhost:8080 in your browser and log in with the following credentials: +Now, open http://127.0.0.1.sslip.io:8080 in your browser and log in with the following credentials: -**Username**: zitadel-admin@zitadel.localhost +**Username**: zitadel-admin@zitadel.127.0.0.1.sslip.io **Password**: Password1! diff --git a/examples/3-cockroach-insecure/zitadel-values.yaml b/examples/3-cockroach-insecure/zitadel-values.yaml index 1659637f..bee90a21 100644 --- a/examples/3-cockroach-insecure/zitadel-values.yaml +++ b/examples/3-cockroach-insecure/zitadel-values.yaml @@ -2,7 +2,7 @@ zitadel: masterkey: x123456789012345678901234567891y configmapConfig: ExternalSecure: false - ExternalDomain: localhost + ExternalDomain: 127.0.0.1.sslip.io TLS: Enabled: false Database: diff --git a/examples/4-cockroach-secure/README.md b/examples/4-cockroach-secure/README.md index 2b0bf954..8201c3a0 100644 --- a/examples/4-cockroach-secure/README.md +++ b/examples/4-cockroach-secure/README.md @@ -9,7 +9,7 @@ Therefore, you create a Kubernetes job that creates a client certificate and key ```bash # Install Cockroach helm repo add cockroachdb https://charts.cockroachdb.com/ -helm install --wait db cockroachdb/cockroachdb --version 11.1.5 --values https://raw.githubusercontent.com/zitadel/zitadel-charts/main/examples/4-cockroach-secure/cockroach-values.yaml +helm install db cockroachdb/cockroachdb --version 11.2.1 --values https://raw.githubusercontent.com/zitadel/zitadel-charts/main/examples/4-cockroach-secure/cockroach-values.yaml # Generate a TLS certificate for the zitadel DB user kubectl apply -f https://raw.githubusercontent.com/zitadel/zitadel-charts/main/examples/4-cockroach-secure/zitadel-cert-job.yaml @@ -26,7 +26,7 @@ When ZITADEL is ready, you can access the GUI via port-forwarding: kubectl port-forward svc/my-zitadel 8080 ``` -Now, open http://localhost:8080 in your browser and log in with the following credentials: +Now, open http://127.0.0.1.sslip.io:8080 in your browser and log in with the following credentials: -**Username**: zitadel-admin@zitadel.localhost +**Username**: zitadel-admin@zitadel.127.0.0.1.sslip.io **Password**: Password1! diff --git a/examples/4-cockroach-secure/zitadel-values.yaml b/examples/4-cockroach-secure/zitadel-values.yaml index 9cdf0828..47553a4b 100644 --- a/examples/4-cockroach-secure/zitadel-values.yaml +++ b/examples/4-cockroach-secure/zitadel-values.yaml @@ -2,7 +2,7 @@ zitadel: masterkey: x123456789012345678901234567891y configmapConfig: ExternalSecure: false - ExternalDomain: localhost + ExternalDomain: 127.0.0.1.sslip.io TLS: Enabled: false Database: diff --git a/examples/5-referenced-secrets/README.md b/examples/5-referenced-secrets/README.md index 94f748f0..f43a9666 100644 --- a/examples/5-referenced-secrets/README.md +++ b/examples/5-referenced-secrets/README.md @@ -30,7 +30,7 @@ When ZITADEL is ready, you can access the GUI via port-forwarding: kubectl port-forward svc/my-zitadel 8080 ``` -Now, open http://localhost:8080 in your browser and log in with the following credentials: +Now, open http://127.0.0.1.sslip.io:8080 in your browser and log in with the following credentials: -**Username**: zitadel-admin@zitadel.localhost +**Username**: zitadel-admin@zitadel.127.0.0.1.sslip.io **Password**: Password1! diff --git a/examples/5-referenced-secrets/zitadel-values.yaml b/examples/5-referenced-secrets/zitadel-values.yaml index da32f8b2..b54a142f 100644 --- a/examples/5-referenced-secrets/zitadel-values.yaml +++ b/examples/5-referenced-secrets/zitadel-values.yaml @@ -2,7 +2,7 @@ zitadel: masterkeySecretName: existing-zitadel-masterkey configmapConfig: ExternalSecure: false - ExternalDomain: localhost + ExternalDomain: 127.0.0.1.sslip.io TLS: Enabled: false Database: diff --git a/examples/6-machine-user/README.md b/examples/6-machine-user/README.md index 58b8034e..ae9bd1a6 100644 --- a/examples/6-machine-user/README.md +++ b/examples/6-machine-user/README.md @@ -30,7 +30,7 @@ When ZITADEL is ready, you can access the GUI via port-forwarding: kubectl port-forward svc/my-zitadel 8080 ``` -Now, open http://localhost:8080 in your browser and log in with the following credentials: +Now, open http://127.0.0.1.sslip.io:8080 in your browser and log in with the following credentials: -**Username**: zitadel-admin@zitadel.localhost +**Username**: zitadel-admin@zitadel.127.0.0.1.sslip.io **Password**: Password1! diff --git a/examples/6-machine-user/zitadel-values.yaml b/examples/6-machine-user/zitadel-values.yaml index 815251f2..621bed3e 100644 --- a/examples/6-machine-user/zitadel-values.yaml +++ b/examples/6-machine-user/zitadel-values.yaml @@ -2,7 +2,7 @@ zitadel: masterkey: x123456789012345678901234567891y configmapConfig: ExternalSecure: false - ExternalDomain: localhost + ExternalDomain: 127.0.0.1.sslip.io TLS: Enabled: false FirstInstance: diff --git a/examples/7-self-signed/README.md b/examples/7-self-signed/README.md new file mode 100644 index 00000000..5b21f233 --- /dev/null +++ b/examples/7-self-signed/README.md @@ -0,0 +1,33 @@ +# Self Signed Example + +For setting up a TLS enabled ZITADEL, you can start using a self-signed certificate. +By setting `zitadel.selfSignedCert.enabled` to true, the chart generates a self-signed cert for each zitadel pod on startup. +By running the commands below, you deploy a simple insecure Postgres database to your Kubernetes cluster [by using the Bitnami chart](https://artifacthub.io/packages/helm/bitnami/postgresql). +Also, you deploy [a correctly configured ZITADEL](https://artifacthub.io/packages/helm/zitadel/zitadel). + +> [!WARNING] +> You only pseudo-secure the incoming connections to ZITADEL, not to your database. +> Anybody with network access to the Postgres database can connect to it and read and write data. +> Use this example only for testing purposes. +> For deploying a secure Postgres database, see [the secure Postgres example](../2-postgres-secure/README.md). + +```bash +# Install Postgres +helm repo add bitnami https://charts.bitnami.com/bitnami +helm install --wait db bitnami/postgresql --version 12.10.0 --values https://raw.githubusercontent.com/zitadel/zitadel-charts/main/examples/7-self-signed/postgres-values.yaml + +# Install ZITADEL +helm repo add zitadel https://charts.zitadel.com +helm install my-zitadel zitadel/zitadel --values https://raw.githubusercontent.com/zitadel/zitadel-charts/main/examples/7-self-signed/zitadel-values.yaml +``` + +When ZITADEL is ready, you can access the GUI via port-forwarding: + +```bash +kubectl port-forward svc/my-zitadel 8080 +``` + +Now, open https://my-iam.127.0.0.1.sslip.io:8080 in your browser and log in with the following credentials: + +**Username**: zitadel-admin@zitadel.my-iam.127.0.0.1.sslip.io +**Password**: Password1! diff --git a/examples/7-self-signed/postgres-values.yaml b/examples/7-self-signed/postgres-values.yaml new file mode 100644 index 00000000..681014c4 --- /dev/null +++ b/examples/7-self-signed/postgres-values.yaml @@ -0,0 +1,3 @@ +primary: + pgHbaConfiguration: | + host all all all trust diff --git a/examples/7-self-signed/zitadel-values.yaml b/examples/7-self-signed/zitadel-values.yaml new file mode 100644 index 00000000..5cb0ae65 --- /dev/null +++ b/examples/7-self-signed/zitadel-values.yaml @@ -0,0 +1,39 @@ +zitadel: + masterkey: x123456789012345678901234567891y + selfSignedCert: + enabled: true + additionalDnsName: my-iam.127.0.0.1.sslip.io + configmapConfig: + ExternalSecure: true + ExternalDomain: my-iam.127.0.0.1.sslip.io + TLS: + Enabled: true + # No need to configure the cert and key path + # The chart automatically configures them via environment variables + Database: + Postgres: + Host: db-postgresql + Port: 5432 + Database: zitadel + MaxOpenConns: 20 + MaxIdleConns: 10 + MaxConnLifetime: 30m + MaxConnIdleTime: 5m + User: + Username: postgres + SSL: + Mode: disable + Admin: + Username: postgres + SSL: + Mode: disable + +# The probes fail if zitadel.selfSignedCert.enabled is true +readinessProbe: + enabled: false + +livenessProbe: + enabled: false + +startupProbe: + enabled: false