package app import ( "context" "strings" "testing" ) func TestServeFailsForUnsafeUploadTokensWithoutLeakingValues(t *testing.T) { duplicateSecret := "duplicate-secret" tests := []struct { name string configPath func(*testing.T) string env map[string]string want string }{ { name: "missing token", configPath: func(t *testing.T) string { return writeServeUploadConfig(t, []string{"DISTRIBUTOR_TEST_MISSING_UPLOAD_TOKEN"}) }, want: "DISTRIBUTOR_TEST_MISSING_UPLOAD_TOKEN", }, { name: "empty token", configPath: func(t *testing.T) string { return writeServeUploadConfig(t, []string{"DISTRIBUTOR_TEST_EMPTY_UPLOAD_TOKEN"}) }, env: map[string]string{"DISTRIBUTOR_TEST_EMPTY_UPLOAD_TOKEN": ""}, want: "DISTRIBUTOR_TEST_EMPTY_UPLOAD_TOKEN", }, { name: "duplicate token", configPath: func(t *testing.T) string { return writeServeUploadConfig(t, []string{ "DISTRIBUTOR_TEST_FIRST_UPLOAD_TOKEN", "DISTRIBUTOR_TEST_SECOND_UPLOAD_TOKEN", }) }, env: map[string]string{ "DISTRIBUTOR_TEST_FIRST_UPLOAD_TOKEN": duplicateSecret, "DISTRIBUTOR_TEST_SECOND_UPLOAD_TOKEN": duplicateSecret, }, want: "same value", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { for name, value := range tt.env { t.Setenv(name, value) } err := Serve(context.Background(), ServeOptions{ConfigPath: tt.configPath(t)}) if err == nil { t.Fatal("Serve() error = nil, want token startup error") } if !strings.Contains(err.Error(), tt.want) { t.Fatalf("Serve() error = %v, want %q", err, tt.want) } if strings.Contains(err.Error(), duplicateSecret) { t.Fatalf("Serve() error exposed token value: %v", err) } }) } } func writeServeUploadConfig(t *testing.T, tokenEnvs []string) string { t.Helper() body := ` server: http: bind: 127.0.0.1:0 upload_tokens: ` for index, tokenEnv := range tokenEnvs { body += ` - id: reporter-` + string(rune('a'+index)) + ` token_env: ` + tokenEnv + ` allow_pipelines: - reports-` + string(rune('a'+index)) + ` ` } body += ` pipelines: ` for index := range tokenEnvs { body += ` - id: reports-` + string(rune('a'+index)) + ` source: backend: http_upload destinations: - id: archive backend: local path: ` + t.TempDir() + ` ` } return writeConfigFile(t, body) }