From 5442bcfb67ab419a8b0d86958ed17a99b6a0b7ea Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 27 Jul 2026 15:47:16 +0800 Subject: [PATCH 1/2] fix(kong): render API credentials before startup --- internal/resources/deployments/kong.go | 10 ++++++++-- internal/resources/deployments/kong_test.go | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/internal/resources/deployments/kong.go b/internal/resources/deployments/kong.go index 5f3f539..9a515be 100644 --- a/internal/resources/deployments/kong.go +++ b/internal/resources/deployments/kong.go @@ -63,7 +63,7 @@ func BuildKongDeployment(project *supabasev1alpha1.SupabaseProject, secretNames env := []corev1.EnvVar{ // Kong configuration {Name: "KONG_DATABASE", Value: "off"}, - {Name: "KONG_DECLARATIVE_CONFIG", Value: "/kong/config/kong.yml"}, + {Name: "KONG_DECLARATIVE_CONFIG", Value: "/tmp/kong.yml"}, {Name: "KONG_DNS_ORDER", Value: "LAST,A,CNAME"}, {Name: "KONG_NGINX_WORKER_PROCESSES", Value: "1"}, {Name: "KONG_PLUGINS", Value: "request-transformer,cors,key-auth,acl,basic-auth"}, @@ -128,7 +128,13 @@ func BuildKongDeployment(project *supabasev1alpha1.SupabaseProject, secretNames Name: KongComponentName, Image: fmt.Sprintf("%s:%s", defaults.KongImage, imageTag), ImagePullPolicy: corev1.PullIfNotPresent, - Env: env, + Command: []string{"/bin/sh", "-ec"}, + Args: []string{`sed \ + -e "s|\${SUPABASE_ANON_KEY}|${SUPABASE_ANON_KEY}|g" \ + -e "s|\${SUPABASE_SERVICE_KEY}|${SUPABASE_SERVICE_KEY}|g" \ + /kong/config/kong.yml > /tmp/kong.yml +exec /docker-entrypoint.sh kong docker-start`}, + Env: env, Ports: []corev1.ContainerPort{ { Name: "http", diff --git a/internal/resources/deployments/kong_test.go b/internal/resources/deployments/kong_test.go index 49003b5..98c8bfe 100644 --- a/internal/resources/deployments/kong_test.go +++ b/internal/resources/deployments/kong_test.go @@ -1,11 +1,31 @@ package deployments import ( + "strings" "testing" "k8s.io/apimachinery/pkg/api/resource" ) +func TestBuildKongDeploymentRendersCredentialTemplateBeforeStartup(t *testing.T) { + project := newTestProject(testNamespace) + deployment := BuildKongDeployment(project, newTestSecretNames()) + container := deployment.Spec.Template.Spec.Containers[0] + + if len(container.Command) == 0 || len(container.Args) == 0 { + t.Fatal("Kong starts without rendering its credential template") + } + if !strings.Contains(container.Args[0], "${SUPABASE_ANON_KEY}") || + !strings.Contains(container.Args[0], "${SUPABASE_SERVICE_KEY}") { + t.Fatal("Kong startup does not substitute both API credentials") + } + for _, variable := range container.Env { + if variable.Name == "KONG_DECLARATIVE_CONFIG" && variable.Value == "/kong/config/kong.yml" { + t.Fatal("Kong still reads the unrendered ConfigMap") + } + } +} + func TestBuildKongDeployment_DefaultWorkerProcesses(t *testing.T) { project := newTestProject(testNamespace) secretNames := newTestSecretNames() From caa635f6a9413e7faccf7d4db659596b32fdf6bd Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 27 Jul 2026 16:02:58 +0800 Subject: [PATCH 2/2] fix(kong): strengthen credential render regression --- internal/resources/deployments/kong_test.go | 65 +++++++++++++++++++-- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/internal/resources/deployments/kong_test.go b/internal/resources/deployments/kong_test.go index 98c8bfe..8b98a42 100644 --- a/internal/resources/deployments/kong_test.go +++ b/internal/resources/deployments/kong_test.go @@ -1,6 +1,9 @@ package deployments import ( + "os" + "os/exec" + "path/filepath" "strings" "testing" @@ -9,20 +12,70 @@ import ( func TestBuildKongDeploymentRendersCredentialTemplateBeforeStartup(t *testing.T) { project := newTestProject(testNamespace) - deployment := BuildKongDeployment(project, newTestSecretNames()) + secretNames := newTestSecretNames() + deployment := BuildKongDeployment(project, secretNames) container := deployment.Spec.Template.Spec.Containers[0] if len(container.Command) == 0 || len(container.Args) == 0 { t.Fatal("Kong starts without rendering its credential template") } - if !strings.Contains(container.Args[0], "${SUPABASE_ANON_KEY}") || - !strings.Contains(container.Args[0], "${SUPABASE_SERVICE_KEY}") { - t.Fatal("Kong startup does not substitute both API credentials") + + wantSecretKeys := map[string]string{ + "SUPABASE_ANON_KEY": "anonKey", + "SUPABASE_SERVICE_KEY": "serviceKey", } + declarativeConfigFound := false for _, variable := range container.Env { - if variable.Name == "KONG_DECLARATIVE_CONFIG" && variable.Value == "/kong/config/kong.yml" { - t.Fatal("Kong still reads the unrendered ConfigMap") + if variable.Name == "KONG_DECLARATIVE_CONFIG" { + declarativeConfigFound = true + if variable.Value != "/tmp/kong.yml" { + t.Fatalf("KONG_DECLARATIVE_CONFIG = %q, want rendered config path", variable.Value) + } + } + secretKey, ok := wantSecretKeys[variable.Name] + if !ok { + continue + } + if variable.ValueFrom == nil || variable.ValueFrom.SecretKeyRef == nil { + t.Fatalf("%s is not sourced from the JWT Secret", variable.Name) + } + ref := variable.ValueFrom.SecretKeyRef + if ref.Name != secretNames.JWT || ref.Key != secretKey { + t.Fatalf("%s secret ref = %s/%s, want %s/%s", variable.Name, ref.Name, ref.Key, secretNames.JWT, secretKey) } + delete(wantSecretKeys, variable.Name) + } + if !declarativeConfigFound { + t.Fatal("KONG_DECLARATIVE_CONFIG is missing") + } + if len(wantSecretKeys) != 0 { + t.Fatalf("missing Kong credential env vars: %v", wantSecretKeys) + } + + templatePath := filepath.Join(t.TempDir(), "kong-template.yml") + renderedPath := filepath.Join(t.TempDir(), "kong.yml") + template := "anon: ${SUPABASE_ANON_KEY}\nservice: ${SUPABASE_SERVICE_KEY}\n" + if err := os.WriteFile(templatePath, []byte(template), 0o600); err != nil { + t.Fatal(err) + } + script := strings.ReplaceAll(container.Args[0], "/kong/config/kong.yml", templatePath) + script = strings.ReplaceAll(script, "/tmp/kong.yml", renderedPath) + script = strings.Replace(script, "exec /docker-entrypoint.sh kong docker-start", ":", 1) + command := exec.Command(container.Command[0], append(container.Command[1:], script)...) + command.Env = append(os.Environ(), + "SUPABASE_ANON_KEY=anon.jwt.value", + "SUPABASE_SERVICE_KEY=service.jwt.value", + ) + if output, err := command.CombinedOutput(); err != nil { + t.Fatalf("render Kong config: %v: %s", err, output) + } + rendered, err := os.ReadFile(renderedPath) + if err != nil { + t.Fatal(err) + } + want := "anon: anon.jwt.value\nservice: service.jwt.value\n" + if string(rendered) != want { + t.Fatalf("rendered Kong config = %q, want %q", rendered, want) } }