diff --git a/src/pkg/cli/compose/config_detector.go b/src/pkg/cli/compose/config_detector.go index 99f2fce95..9cf1364f7 100644 --- a/src/pkg/cli/compose/config_detector.go +++ b/src/pkg/cli/compose/config_detector.go @@ -6,20 +6,20 @@ import ( "github.com/DefangLabs/secret-detector/pkg/scanner" ) -func IsSecret(input string) (bool, error) { +func IsSecret(key, value string) (bool, []string, error) { // DetectConfig checks if the input string contains any sensitive information - detectorTypes, err := detectConfig(input) + detectorTypes, err := detectConfig(key + ": " + value) if err != nil { - return false, fmt.Errorf("failed to detect config: %w", err) + return false, nil, fmt.Errorf("failed to detect config: %w", err) } // If no detectors were triggered, return false if len(detectorTypes) == 0 { - return false, nil + return false, nil, nil } // If any detectors were triggered, return true - return true, nil + return true, detectorTypes, nil } // assume that the input is a key-value pair string @@ -33,9 +33,9 @@ func detectConfig(input string) (detectorTypes []string, err error) { // create a custom scanner config cfg := scanner.NewConfigWithDefaults() - cfg.Transformers = []string{"json"} + cfg.Transformers = []string{"yaml"} cfg.DetectorConfigs["keyword"] = []string{"3"} - cfg.DetectorConfigs["high_entropy_string"] = []string{"4"} + cfg.DetectorConfigs["high_entropy_string"] = []string{"3.7"} // create a scanner from scanner config scannerClient, err := scanner.NewScannerFromConfig(cfg) diff --git a/src/pkg/cli/compose/config_detector_test.go b/src/pkg/cli/compose/config_detector_test.go index c95302eca..99fe41529 100644 --- a/src/pkg/cli/compose/config_detector_test.go +++ b/src/pkg/cli/compose/config_detector_test.go @@ -18,6 +18,7 @@ func TestDetectConfig(t *testing.T) { {"AROA1234567890ABCDEF", []string{"AWS Client ID"}}, {"REDIS_URL=rediss://foo:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240", []string{"URL with password"}}, {"REDIS_URL=rediss://:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240", []string{"URL with password"}}, + {"ENCRYPTION_KEY: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", []string{"High entropy string"}}, } for _, tt := range tests { diff --git a/src/pkg/cli/compose/validation.go b/src/pkg/cli/compose/validation.go index 3382aabdb..b8f4e35ce 100644 --- a/src/pkg/cli/compose/validation.go +++ b/src/pkg/cli/compose/validation.go @@ -204,19 +204,16 @@ func validateService(svccfg *composeTypes.ServiceConfig, project *composeTypes.P // check for compose file environment variables that may be sensitive for key, value := range svccfg.Environment { if value != nil { - // format input as a key-value pair string - input := key + "=" + *value - // call detectConfig to check for sensitive information - ds, err := detectConfig(input) + isSecret, ds, err := IsSecret(key, *value) if err != nil { return fmt.Errorf("service %q: %w", svccfg.Name, err) } // show warning if sensitive information is detected - if len(ds) > 0 { + if isSecret { term.Warnf("service %q: environment %q may contain sensitive information; consider using 'defang config set %s' to securely store this value", svccfg.Name, key, key) - term.Debugf("service %q: environment %q may contain detected secrets of type: %q", svccfg.Name, key, ds) + term.Debugf("service %q: environment %q may contain detected secrets of type: %v", svccfg.Name, key, ds) } } } diff --git a/src/pkg/cli/composeUp.go b/src/pkg/cli/composeUp.go index 4ce87e6fb..d1da23dd2 100644 --- a/src/pkg/cli/composeUp.go +++ b/src/pkg/cli/composeUp.go @@ -87,7 +87,7 @@ func ComposeUp(ctx context.Context, fabric client.FabricClient, provider client. if upload != compose.UploadModeIgnore { // Ignore missing configs in preview mode, because we don't want to fail the preview if some configs are missing. if upload != compose.UploadModeEstimate { - if err := PrintConfigSummaryAndValidate(ctx, provider, project); err != nil { + if err := PrintRedactedConfigSummaryAndValidate(ctx, provider, project); err != nil { return nil, project, err } } diff --git a/src/pkg/cli/configResolution.go b/src/pkg/cli/configResolution.go index d7d30ccde..a5ddd5a9e 100644 --- a/src/pkg/cli/configResolution.go +++ b/src/pkg/cli/configResolution.go @@ -19,7 +19,7 @@ type configOutput struct { Source Source `json:"source,omitempty"` } -const configMaskedValue = "*****" +const configMaskedValue = "******" type Source string @@ -33,8 +33,16 @@ func (s Source) String() string { return string(s) } +func maskTrailingConfigValue(value string) string { + // Mask the value if it looks like a secret and only show the first 4 characters + if len(value) <= 4 { + return configMaskedValue + } + return value[:4] + strings.Repeat("*", 2) +} + // determineConfigSource determines the source of an environment variable -// and returns the appropriate source type and value to display +// and returns the appropriate source type and value to display. func determineConfigSource(envKey string, envValue *string, defangConfigs map[string]struct{}) (Source, string) { // If the key itself is a defang config, mask it if _, isDefangConfig := defangConfigs[envKey]; isDefangConfig { @@ -57,7 +65,9 @@ func determineConfigSource(envKey string, envValue *string, defangConfigs map[st return SourceComposeFile, *envValue } -func printConfigResolutionSummary(project *types.Project, defangConfig []string) error { +// printConfigResolutionSummary prints a summary of where each environment variable in the compose file is coming from (compose file, defang config, or interpolation). +// If redact is true, it will mask values that are from the compose file and look like secrets. +func printConfigResolutionSummary(project *types.Project, defangConfig []string, redact bool) error { configset := make(map[string]struct{}) for _, name := range defangConfig { configset[name] = struct{}{} @@ -68,6 +78,16 @@ func printConfigResolutionSummary(project *types.Project, defangConfig []string) for serviceName, service := range project.Services { for envKey, envValue := range service.Environment { source, value := determineConfigSource(envKey, envValue, configset) + if redact && source == SourceComposeFile { + isSecret, _, err := compose.IsSecret(envKey, value) + if err != nil { + return err + } + + if isSecret { + value = maskTrailingConfigValue(value) + } + } projectEnvVars = append(projectEnvVars, configOutput{ Service: serviceName, Environment: envKey, @@ -97,13 +117,13 @@ func printConfigResolutionSummary(project *types.Project, defangConfig []string) return term.Table(projectEnvVars, "Service", "Environment", "Source", "Value") } -func PrintConfigSummaryAndValidate(ctx context.Context, provider client.Provider, project *compose.Project) error { +func printConfigSummaryAndValidate(ctx context.Context, provider client.Provider, project *compose.Project, redact bool) error { configs, err := provider.ListConfig(ctx, &defangv1.ListConfigsRequest{Project: project.Name}) if err != nil { return err } - err = printConfigResolutionSummary(project, configs.Names) + err = printConfigResolutionSummary(project, configs.Names, redact) if err != nil { return err } @@ -115,3 +135,11 @@ func PrintConfigSummaryAndValidate(ctx context.Context, provider client.Provider return nil } + +func PrintConfigSummaryAndValidate(ctx context.Context, provider client.Provider, project *compose.Project) error { + return printConfigSummaryAndValidate(ctx, provider, project, false) +} + +func PrintRedactedConfigSummaryAndValidate(ctx context.Context, provider client.Provider, project *compose.Project) error { + return printConfigSummaryAndValidate(ctx, provider, project, true) +} diff --git a/src/pkg/cli/configResolution_test.go b/src/pkg/cli/configResolution_test.go index 5b6e74c2d..927cfc60b 100644 --- a/src/pkg/cli/configResolution_test.go +++ b/src/pkg/cli/configResolution_test.go @@ -12,7 +12,7 @@ import ( ) func TestPrintConfigResolutionSummary(t *testing.T) { - testAllConfigResolutionFiles(t, func(t *testing.T, name, path string) { + testAllConfigResolutionFiles(t, "testdata/config-resolution", func(t *testing.T, name, path string) { stdout, _ := term.SetupTestTerm(t) loader := compose.NewLoader(compose.WithPath(path)) @@ -36,7 +36,7 @@ func TestPrintConfigResolutionSummary(t *testing.T) { defangConfigs = []string{} } - err = printConfigResolutionSummary(proj, defangConfigs) + err = printConfigResolutionSummary(proj, defangConfigs, false) if err != nil { t.Fatalf("PrintConfigResolutionSummary() error = %v", err) } @@ -50,11 +50,35 @@ func TestPrintConfigResolutionSummary(t *testing.T) { }) } -func testAllConfigResolutionFiles(t *testing.T, f func(t *testing.T, name, path string)) { +func TestPrintRedactedConfigResolutionSummary(t *testing.T) { + testAllConfigResolutionFiles(t, "testdata/redact-config", func(t *testing.T, name, path string) { + stdout, _ := term.SetupTestTerm(t) + + loader := compose.NewLoader(compose.WithPath(path)) + proj, err := loader.LoadProject(t.Context()) + if err != nil { + t.Fatal(err) + } + + err = printConfigResolutionSummary(proj, nil, true) + if err != nil { + t.Fatalf("PrintConfigResolutionSummary() error = %v", err) + } + + output := stdout.Bytes() + + // Compare the output with the golden file + if err := pkg.Compare(output, path+".golden"); err != nil { + t.Error(err) + } + }) +} + +func testAllConfigResolutionFiles(t *testing.T, dir string, f func(t *testing.T, name, path string)) { t.Helper() composeRegex := regexp.MustCompile(`^(?i)(docker-)?compose.ya?ml$`) - err := filepath.WalkDir("testdata/configresolution", func(path string, d os.DirEntry, err error) error { + err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { if err != nil || d.IsDir() || !composeRegex.MatchString(d.Name()) { return err } diff --git a/src/pkg/cli/testdata/configresolution/compose-file-only/compose.yaml b/src/pkg/cli/testdata/config-resolution/compose-file-only/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/compose-file-only/compose.yaml rename to src/pkg/cli/testdata/config-resolution/compose-file-only/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/compose-file-only/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/compose-file-only/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/compose-file-only/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/compose-file-only/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/defang-config-only/compose.yaml b/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/defang-config-only/compose.yaml rename to src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml diff --git a/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml.golden new file mode 100644 index 000000000..87c295e13 --- /dev/null +++ b/src/pkg/cli/testdata/config-resolution/defang-config-only/compose.yaml.golden @@ -0,0 +1,6 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +service1 API_TOKEN Config ****** +service1 DB_USER Config ****** +service1 SECRET_KEY Config ****** diff --git a/src/pkg/cli/testdata/configresolution/empty-values/compose.yaml b/src/pkg/cli/testdata/config-resolution/empty-values/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/empty-values/compose.yaml rename to src/pkg/cli/testdata/config-resolution/empty-values/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/empty-values/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/empty-values/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/empty-values/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/empty-values/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/env-values/.env b/src/pkg/cli/testdata/config-resolution/env-values/.env similarity index 100% rename from src/pkg/cli/testdata/configresolution/env-values/.env rename to src/pkg/cli/testdata/config-resolution/env-values/.env diff --git a/src/pkg/cli/testdata/configresolution/env-values/compose.yaml b/src/pkg/cli/testdata/config-resolution/env-values/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/env-values/compose.yaml rename to src/pkg/cli/testdata/config-resolution/env-values/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/env-values/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/env-values/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/env-values/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/env-values/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/interpolated-values/compose.yaml b/src/pkg/cli/testdata/config-resolution/interpolated-values/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/interpolated-values/compose.yaml rename to src/pkg/cli/testdata/config-resolution/interpolated-values/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/interpolated-values/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/interpolated-values/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/interpolated-values/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/interpolated-values/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/mixed-sources/.env b/src/pkg/cli/testdata/config-resolution/mixed-sources/.env similarity index 100% rename from src/pkg/cli/testdata/configresolution/mixed-sources/.env rename to src/pkg/cli/testdata/config-resolution/mixed-sources/.env diff --git a/src/pkg/cli/testdata/configresolution/mixed-sources/compose.yaml b/src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/mixed-sources/compose.yaml rename to src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/mixed-sources/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml.golden similarity index 86% rename from src/pkg/cli/testdata/configresolution/mixed-sources/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml.golden index 68a9f39a0..be6594f45 100644 --- a/src/pkg/cli/testdata/configresolution/mixed-sources/compose.yaml.golden +++ b/src/pkg/cli/testdata/config-resolution/mixed-sources/compose.yaml.golden @@ -4,4 +4,4 @@ SERVICE ENVIRONMENT SOURCE VALUE service1 FROM_ENV Compose from_ENV service1 PLAIN_VAR Compose plain_value service1 PUBLIC_URL Config (interpolated) https://example-${SECRET_KEY}-from_ENV.com -service1 SECRET_KEY Config ***** +service1 SECRET_KEY Config ****** diff --git a/src/pkg/cli/testdata/configresolution/multiple-services/compose.yaml b/src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/multiple-services/compose.yaml rename to src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/multiple-services/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml.golden similarity index 76% rename from src/pkg/cli/testdata/configresolution/multiple-services/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml.golden index a58ac5cbc..e9c9026be 100644 --- a/src/pkg/cli/testdata/configresolution/multiple-services/compose.yaml.golden +++ b/src/pkg/cli/testdata/config-resolution/multiple-services/compose.yaml.golden @@ -2,8 +2,8 @@  SERVICE ENVIRONMENT SOURCE VALUE service1 APP_ENV Compose production -service1 DATABASE_URL Config ***** +service1 DATABASE_URL Config ****** service1 LOG_LEVEL Compose info -service2 REDIS_PASSWORD Config ***** +service2 REDIS_PASSWORD Config ****** service2 REDIS_PORT Compose 6379 service3 DB_USER Compose Defang diff --git a/src/pkg/cli/testdata/configresolution/no-environment/compose.yaml b/src/pkg/cli/testdata/config-resolution/no-environment/compose.yaml similarity index 100% rename from src/pkg/cli/testdata/configresolution/no-environment/compose.yaml rename to src/pkg/cli/testdata/config-resolution/no-environment/compose.yaml diff --git a/src/pkg/cli/testdata/configresolution/no-environment/compose.yaml.golden b/src/pkg/cli/testdata/config-resolution/no-environment/compose.yaml.golden similarity index 100% rename from src/pkg/cli/testdata/configresolution/no-environment/compose.yaml.golden rename to src/pkg/cli/testdata/config-resolution/no-environment/compose.yaml.golden diff --git a/src/pkg/cli/testdata/configresolution/defang-config-only/compose.yaml.golden b/src/pkg/cli/testdata/configresolution/defang-config-only/compose.yaml.golden deleted file mode 100644 index 804cce71c..000000000 --- a/src/pkg/cli/testdata/configresolution/defang-config-only/compose.yaml.golden +++ /dev/null @@ -1,6 +0,0 @@ - * Service environment variables resolution summary: - -SERVICE ENVIRONMENT SOURCE VALUE -service1 API_TOKEN Config ***** -service1 DB_USER Config ***** -service1 SECRET_KEY Config ***** diff --git a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml new file mode 100644 index 000000000..df371d8e1 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml @@ -0,0 +1,9 @@ +services: + backend: + image: node + environment: + APP_NAME: my-application + API_KEY: api-key=50m34p1k3y + SECRET_TOKEN: secret_token=ab12cd34ef56 + AUTH_PASSWORD: password=hunter12345 + NORMAL_CONFIG: debug diff --git a/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden new file mode 100644 index 000000000..ea393ca6a --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/api-keys/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +backend API_KEY Compose api-** +backend APP_NAME Compose my-application +backend AUTH_PASSWORD Compose pass** +backend NORMAL_CONFIG Compose debug +backend SECRET_TOKEN Compose secr** diff --git a/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml new file mode 100644 index 000000000..c74c0520c --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml @@ -0,0 +1,9 @@ +services: + deployer: + image: alpine + environment: + GITHUB_TOKEN: ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 + AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE + AWS_SECRET_ACCESS_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + AWS_CLIENT_ID: AROA1234567890ABCDEF + REGION: us-east-1 diff --git a/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden new file mode 100644 index 000000000..6790ed481 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/cloud-credentials/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +deployer AWS_ACCESS_KEY_ID Compose AKIA** +deployer AWS_CLIENT_ID Compose AROA** +deployer AWS_SECRET_ACCESS_KEY Compose wJal** +deployer GITHUB_TOKEN Compose ghp_** +deployer REGION Compose us-east-1 diff --git a/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml new file mode 100644 index 000000000..49c08d7be --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml @@ -0,0 +1,10 @@ +services: + api: + image: node + environment: + DATABASE_URL: postgres://dbuser:p455w0rd@db.example.com:5432/myapp + MONGO_URI: mongodb://admin:s3cretP4ss@mongo.example.com:27017/mydb + MYSQL_URL: mysql://root:r00tP4ssw0rd@mysql.example.com:3306/app + REDIS_URL: rediss://default:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@redis.example.com:6380 + DB_HOST: db.example.com + DB_PORT: "5432" diff --git a/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden new file mode 100644 index 000000000..24ba60e75 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/database-urls/compose.yaml.golden @@ -0,0 +1,9 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +api DATABASE_URL Compose post** +api DB_HOST Compose db.example.com +api DB_PORT Compose 5432 +api MONGO_URI Compose mong** +api MYSQL_URL Compose mysq** +api REDIS_URL Compose redi** diff --git a/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml b/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml new file mode 100644 index 000000000..28e2622fc --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml @@ -0,0 +1,12 @@ +services: + service1: + image: nginx + environment: + EMPTY_VAR: + WITH_VALUE: some_value + service2: + image: nginx + environment: + - EMPTY_STRING= + - EMPTY_VAR + - WITH_VALUE=some_value diff --git a/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml.golden new file mode 100644 index 000000000..e3587b17a --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/empty-values/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +service1 EMPTY_VAR Config +service1 WITH_VALUE Compose some_value +service2 EMPTY_STRING Compose +service2 EMPTY_VAR Config +service2 WITH_VALUE Compose some_value diff --git a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml new file mode 100644 index 000000000..512d75b01 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml @@ -0,0 +1,9 @@ +services: + app: + image: python + environment: + SESSION_SECRET: VEfk5vO0Q53VkK_uicor + ENCRYPTION_KEY: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 + SIGNING_KEY: xK9mPqR7sT2vW5yZ8aB3cD6eF + APP_ENV: production + LOG_LEVEL: info diff --git a/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden new file mode 100644 index 000000000..e46e74770 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/high-entropy-strings/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +app APP_ENV Compose production +app ENCRYPTION_KEY Compose 9f86** +app LOG_LEVEL Compose info +app SESSION_SECRET Compose VEfk** +app SIGNING_KEY Compose xK9m** diff --git a/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml new file mode 100644 index 000000000..13f4f1f1c --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml @@ -0,0 +1,16 @@ +services: + frontend: + image: nginx + environment: + APP_NAME: my-frontend + PORT: "3000" + backend: + image: node + environment: + APP_NAME: my-backend + PORT: "8080" + DATABASE_URL: postgres://admin:p455w0rd@db.example.com:5432/myapp + GITHUB_TOKEN: ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 + API_KEY: api-key=50m34p1k3y + LOG_LEVEL: info + NODE_ENV: production diff --git a/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden new file mode 100644 index 000000000..3588e8a1c --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/mixed-secrets-and-plain/compose.yaml.golden @@ -0,0 +1,12 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +backend API_KEY Compose api-** +backend APP_NAME Compose my-backend +backend DATABASE_URL Compose post** +backend GITHUB_TOKEN Compose ghp_** +backend LOG_LEVEL Compose info +backend NODE_ENV Compose production +backend PORT Compose 8080 +frontend APP_NAME Compose my-frontend +frontend PORT Compose 3000 diff --git a/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml b/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml new file mode 100644 index 000000000..770946440 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml @@ -0,0 +1,11 @@ +services: + web: + image: nginx + environment: + APP_ENV: production + LOG_LEVEL: info + PORT: "8080" + API_URL: https://api.example.com + DOCS_PATH: /leaderboard/api/hubs + NODE_ENV: production + GREETING: not a secret diff --git a/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml.golden new file mode 100644 index 000000000..c4eb8304f --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/not-secrets/compose.yaml.golden @@ -0,0 +1,10 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +web API_URL Compose https://api.example.com +web APP_ENV Compose production +web DOCS_PATH Compose /leaderboard/api/hubs +web GREETING Compose not a secret +web LOG_LEVEL Compose info +web NODE_ENV Compose production +web PORT Compose 8080 diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env new file mode 100644 index 000000000..11e93cbea --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/.env @@ -0,0 +1,5 @@ +GITHUB_TOKEN=ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890 +DATABASE_URL=postgres://dbuser:p455w0rd@db.example.com:5432/myapp +POSTGRES_PASSWORD=p455w0rd +API_SECRET=VEfk5vO0Q53VkK_uicor +APP_ENV=production diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml new file mode 100644 index 000000000..ea4c07afe --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml @@ -0,0 +1,10 @@ +services: + web: + image: nginx + environment: + GITHUB_TOKEN: ${GITHUB_TOKEN} + DATABASE_URL: ${DATABASE_URL} + POSTGRES_URL: postgres://dbuser:${POSTGRES_PASSWORD}@db.example.com:5432/myapp + API_SECRET: ${API_SECRET} + APP_ENV: ${APP_ENV} + STATIC_VALUE: hello diff --git a/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden new file mode 100644 index 000000000..ec0c89826 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/secrets-in-env-file/compose.yaml.golden @@ -0,0 +1,9 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +web API_SECRET Compose VEfk** +web APP_ENV Compose production +web DATABASE_URL Compose post** +web GITHUB_TOKEN Compose ghp_** +web POSTGRES_URL Compose post** +web STATIC_VALUE Compose hello diff --git a/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml new file mode 100644 index 000000000..eeac7adf0 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml @@ -0,0 +1,9 @@ +services: + web: + image: nginx + environment: + SAFE_URL: https://example.com/api/v1 + WEBHOOK_URL: https://user:p455w0rd@example.com + CALLBACK_URL: https://user:p845w0rd@hooks.example.com/callback + REDIS_URL: rediss://foo:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240 + REDIS_ALT_URL: rediss://:p41fce90d44ac1d891bd21fdbc5dfc1bd7f163e33a6934c30093eaf56c1c23937@ec2-98-85-106-43.compute-1.amazonaws.com:8240 diff --git a/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden new file mode 100644 index 000000000..15d028fb3 --- /dev/null +++ b/src/pkg/cli/testdata/redact-config/url-with-password/compose.yaml.golden @@ -0,0 +1,8 @@ + * Service environment variables resolution summary: + +SERVICE ENVIRONMENT SOURCE VALUE +web CALLBACK_URL Compose http** +web REDIS_ALT_URL Compose redi** +web REDIS_URL Compose redi** +web SAFE_URL Compose https://example.com/api/v1 +web WEBHOOK_URL Compose http** diff --git a/src/pkg/migrate/migrate.go b/src/pkg/migrate/migrate.go index 600fa8395..fb74a14d8 100644 --- a/src/pkg/migrate/migrate.go +++ b/src/pkg/migrate/migrate.go @@ -97,7 +97,7 @@ func setupFromHeroku(ctx context.Context, fabric client.FabricClient, surveyor s func sanitizeHerokuApplicationInfo(info HerokuApplicationInfo) (interface{}, error) { for key, value := range info.ConfigVars { // Redact sensitive information in config vars - isSecret, err := compose.IsSecret(value) + isSecret, _, err := compose.IsSecret(key, value) if err != nil { return nil, fmt.Errorf("failed to check if config var %q is a secret: %w", key, err) }