diff --git a/cmd/config/get_test.go b/cmd/config/get_test.go index 38529c05..0d4da6dd 100644 --- a/cmd/config/get_test.go +++ b/cmd/config/get_test.go @@ -62,3 +62,34 @@ func TestConfigGetCmd_NoKey(t *testing.T) { err := testutils_cobra.ExecutePingcli(t, "config", "get") testutils.CheckExpectedError(t, err, &expectedErrorPattern) } + +// https://pkg.go.dev/testing#hdr-Examples +func Example_getEmptyMaskedValue() { + t := testing.T{} + _ = testutils_cobra.ExecutePingcli(&t, "config", "get", options.RequestAccessTokenOption.ViperKey) + + // Output: + // Configuration values for profile 'default' and key 'request.accessToken': + // request.accessToken= + // request.accessTokenExpiry=0 +} + +// https://pkg.go.dev/testing#hdr-Examples +func Example_getMaskedValue() { + t := testing.T{} + _ = testutils_cobra.ExecutePingcli(&t, "config", "get", options.PingFederateClientCredentialsAuthClientSecretOption.ViperKey) + + // Output: + // Configuration values for profile 'default' and key 'service.pingfederate.authentication.clientCredentialsAuth.clientSecret': + // service.pingfederate.authentication.clientCredentialsAuth.clientSecret=******** +} + +// https://pkg.go.dev/testing#hdr-Examples +func Example_getUnmaskedValue() { + t := testing.T{} + _ = testutils_cobra.ExecutePingcli(&t, "config", "get", options.RootColorOption.ViperKey) + + // Output: + // Configuration values for profile 'default' and key 'noColor': + // noColor=true +} diff --git a/cmd/config/set_test.go b/cmd/config/set_test.go index 60e14721..3c787b38 100644 --- a/cmd/config/set_test.go +++ b/cmd/config/set_test.go @@ -83,3 +83,23 @@ func TestConfigSetCmd_InvalidFlag(t *testing.T) { err := testutils_cobra.ExecutePingcli(t, "config", "set", "--invalid") testutils.CheckExpectedError(t, err, &expectedErrorPattern) } + +// https://pkg.go.dev/testing#hdr-Examples +func Example_setMaskedValue() { + t := testing.T{} + _ = testutils_cobra.ExecutePingcli(&t, "config", "set", fmt.Sprintf("%s=%s", options.PingFederateBasicAuthPasswordOption.ViperKey, "1234")) + + // Output: + // SUCCESS: Configuration set successfully: + // service.pingfederate.authentication.basicAuth.password=******** +} + +// https://pkg.go.dev/testing#hdr-Examples +func Example_setUnmaskedValue() { + t := testing.T{} + _ = testutils_cobra.ExecutePingcli(&t, "config", "set", fmt.Sprintf("%s=%s", options.RootColorOption.ViperKey, "true")) + + // Output: + // SUCCESS: Configuration set successfully: + // noColor=true +} diff --git a/cmd/config/unset_test.go b/cmd/config/unset_test.go index cdbe716e..eefd3b5d 100644 --- a/cmd/config/unset_test.go +++ b/cmd/config/unset_test.go @@ -72,3 +72,23 @@ func TestConfigUnsetCmd_HelpFlag(t *testing.T) { err = testutils_cobra.ExecutePingcli(t, "config", "unset", "-h") testutils.CheckExpectedError(t, err, nil) } + +// https://pkg.go.dev/testing#hdr-Examples +func Example_unsetMaskedValue() { + t := testing.T{} + _ = testutils_cobra.ExecutePingcli(&t, "config", "unset", options.PingFederateBasicAuthUsernameOption.ViperKey) + + // Output: + // SUCCESS: Configuration unset successfully: + // service.pingfederate.authentication.basicAuth.username= +} + +// https://pkg.go.dev/testing#hdr-Examples +func Example_unsetUnmaskedValue() { + t := testing.T{} + _ = testutils_cobra.ExecutePingcli(&t, "config", "unset", options.RootOutputFormatOption.ViperKey) + + // Output: + // SUCCESS: Configuration unset successfully: + // outputFormat=text +} diff --git a/internal/commands/config/get_internal.go b/internal/commands/config/get_internal.go index 18056ca3..0399dc33 100644 --- a/internal/commands/config/get_internal.go +++ b/internal/commands/config/get_internal.go @@ -2,6 +2,7 @@ package config_internal import ( "fmt" + "strings" "github.com/pingidentity/pingcli/internal/configuration" "github.com/pingidentity/pingcli/internal/configuration/options" @@ -19,12 +20,26 @@ func RunInternalConfigGet(viperKey string) (err error) { return fmt.Errorf("failed to get configuration: %v", err) } - yamlStr, err := profiles.GetMainConfig().ProfileViperValue(pName, viperKey) - if err != nil { - return fmt.Errorf("failed to get configuration: %v", err) + msgStr := fmt.Sprintf("Configuration values for profile '%s' and key '%s':\n", pName, viperKey) + + for _, opt := range options.Options() { + if opt.ViperKey == "" || !strings.Contains(opt.ViperKey, viperKey) { + continue + } + + vVal, _, err := profiles.ViperValueFromOption(opt) + if err != nil { + return fmt.Errorf("failed to get configuration: %v", err) + } + + if opt.Sensitive { + msgStr += fmt.Sprintf("%s=%s\n", opt.ViperKey, profiles.MaskValue(vVal)) + } else { + msgStr += fmt.Sprintf("%s=%s\n", opt.ViperKey, vVal) + } } - output.Message(yamlStr, nil) + output.Message(msgStr, nil) return nil } @@ -37,11 +52,11 @@ func readConfigGetOptions() (pName string, err error) { } if err != nil { - return pName, err + return "", err } if pName == "" { - return pName, fmt.Errorf("unable to determine profile to get configuration from") + return "", fmt.Errorf("unable to determine profile to get configuration from") } return pName, nil diff --git a/internal/commands/config/set_internal.go b/internal/commands/config/set_internal.go index 4c6e4a7a..081011da 100644 --- a/internal/commands/config/set_internal.go +++ b/internal/commands/config/set_internal.go @@ -45,12 +45,20 @@ func RunInternalConfigSet(kvPair string) (err error) { return fmt.Errorf("failed to set configuration: %v", err) } - yamlStr, err := profiles.GetMainConfig().ProfileToString(pName) + msgStr := "Configuration set successfully:\n" + + vVal, _, err := profiles.ViperValueFromOption(opt) if err != nil { return fmt.Errorf("failed to set configuration: %v", err) } - output.Success("Configuration set successfully", map[string]interface{}{"Profile YAML": yamlStr}) + if opt.Sensitive { + msgStr += fmt.Sprintf("%s=%s", vKey, profiles.MaskValue(vVal)) + } else { + msgStr += fmt.Sprintf("%s=%s", vKey, vVal) + } + + output.Success(msgStr, nil) return nil } diff --git a/internal/commands/config/unset_internal.go b/internal/commands/config/unset_internal.go index 1fe4ee7d..6e10e1e2 100644 --- a/internal/commands/config/unset_internal.go +++ b/internal/commands/config/unset_internal.go @@ -35,12 +35,20 @@ func RunInternalConfigUnset(viperKey string) (err error) { return fmt.Errorf("failed to unset configuration: %v", err) } - yamlStr, err := profiles.GetMainConfig().ProfileToString(pName) + msgStr := "Configuration unset successfully:\n" + + vVal, _, err := profiles.ViperValueFromOption(opt) if err != nil { - return fmt.Errorf("failed to unset configuration: %v", err) + return fmt.Errorf("failed to set configuration: %v", err) + } + + if opt.Sensitive { + msgStr += fmt.Sprintf("%s=%s", viperKey, profiles.MaskValue(vVal)) + } else { + msgStr += fmt.Sprintf("%s=%s", viperKey, vVal) } - output.Success("Configuration unset successfully", map[string]interface{}{"Profile YAML": yamlStr}) + output.Success(msgStr, nil) return nil } diff --git a/internal/commands/config/view_profile_internal.go b/internal/commands/config/view_profile_internal.go index 1cf374d4..476482ea 100644 --- a/internal/commands/config/view_profile_internal.go +++ b/internal/commands/config/view_profile_internal.go @@ -19,14 +19,32 @@ func RunInternalConfigViewProfile(args []string) (err error) { } } - profileStr, err := profiles.GetMainConfig().ProfileToString(pName) + // Validate the profile name + err = profiles.GetMainConfig().ValidateExistingProfileName(pName) if err != nil { return fmt.Errorf("failed to view profile: %v", err) } - profileStr = fmt.Sprintf("Profile: %s\n\n%s", pName, profileStr) + msgStr := fmt.Sprintf("Configuration for profile '%s':\n", pName) - output.Message(profileStr, nil) + for _, opt := range options.Options() { + if opt.ViperKey == "" { + continue + } + + vVal, _, err := profiles.ViperValueFromOption(opt) + if err != nil { + return fmt.Errorf("failed to view profile: %v", err) + } + + if opt.Sensitive { + msgStr += fmt.Sprintf("%s=%s\n", opt.ViperKey, profiles.MaskValue(vVal)) + } else { + msgStr += fmt.Sprintf("%s=%s\n", opt.ViperKey, vVal) + } + } + + output.Message(msgStr, nil) return nil } diff --git a/internal/commands/platform/export_internal.go b/internal/commands/platform/export_internal.go index 67ddae83..d90a21f0 100644 --- a/internal/commands/platform/export_internal.go +++ b/internal/commands/platform/export_internal.go @@ -335,19 +335,8 @@ func initPingOneApiClient(ctx context.Context, pingcliVersion string) (err error pingoneApiClient, err = apiConfig.APIClient(ctx) if err != nil { - return fmt.Errorf(`failed to initialize pingone API client. -%v - -configuration values used for client initialization: -worker client ID - %s -worker client secret - %s -worker environment ID - %s -pingone region - %s`, - err, - pingoneApiClientId, - strings.Repeat("*", len(clientSecret)), - environmentID, - regionCode) + return fmt.Errorf("failed to initialize pingone API client. Check worker client ID, worker client secret,"+ + " worker environment ID, and pingone region code configuration values. %v", err) } return nil diff --git a/internal/configuration/config/add_profile.go b/internal/configuration/config/add_profile.go index d98d8f86..30a3e8b2 100644 --- a/internal/configuration/config/add_profile.go +++ b/internal/configuration/config/add_profile.go @@ -28,8 +28,9 @@ func initAddProfileDescriptionOption() { Usage: "The description of the new configuration profile.", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "", // No viper key + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "", // No viper key } } @@ -49,8 +50,9 @@ func initAddProfileNameOption() { Usage: "The name of the new configuration profile.", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "", // No viper key + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "", // No viper key } } @@ -72,7 +74,8 @@ func initAddProfileSetActiveOption() { Value: cobraValue, NoOptDefVal: "true", // Make this flag a boolean flag }, - Type: options.ENUM_BOOL, - ViperKey: "", // No viper key + Sensitive: false, + Type: options.ENUM_BOOL, + ViperKey: "", // No viper key } } diff --git a/internal/configuration/config/delete_profile.go b/internal/configuration/config/delete_profile.go index 9c0d0a21..b26773f0 100644 --- a/internal/configuration/config/delete_profile.go +++ b/internal/configuration/config/delete_profile.go @@ -28,7 +28,8 @@ func initDeleteAutoAcceptOption() { Value: cobraValue, NoOptDefVal: "true", // Make the flag a boolean flag }, - Type: options.ENUM_STRING, - ViperKey: "", // No viper key + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "", // No viper key } } diff --git a/internal/configuration/options/options.go b/internal/configuration/options/options.go index 6bef857e..2afeaa85 100644 --- a/internal/configuration/options/options.go +++ b/internal/configuration/options/options.go @@ -1,6 +1,11 @@ package options -import "github.com/spf13/pflag" +import ( + "slices" + "strings" + + "github.com/spf13/pflag" +) type OptionType string @@ -27,12 +32,13 @@ type Option struct { DefaultValue pflag.Value EnvVar string Flag *pflag.Flag + Sensitive bool Type OptionType ViperKey string } func Options() []Option { - return []Option{ + optList := []Option{ PingOneAuthenticationTypeOption, PingOneAuthenticationWorkerClientIDOption, PingOneAuthenticationWorkerClientSecretOption, @@ -79,6 +85,13 @@ func Options() []Option { RequestAccessTokenExpiryOption, RequestFailOption, } + + // Sort the options list by viper key + slices.SortFunc(optList, func(opt1, opt2 Option) int { + return strings.Compare(opt1.ViperKey, opt2.ViperKey) + }) + + return optList } // pingone service options diff --git a/internal/configuration/platform/export.go b/internal/configuration/platform/export.go index 61c50a36..cbe4bc63 100644 --- a/internal/configuration/platform/export.go +++ b/internal/configuration/platform/export.go @@ -39,8 +39,9 @@ func initFormatOption() { ), Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "export.format", + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "export.format", } } @@ -71,8 +72,9 @@ func initServicesOption() { ), Value: cobraValue, }, - Type: options.ENUM_EXPORT_SERVICES, - ViperKey: "export.services", + Sensitive: false, + Type: options.ENUM_EXPORT_SERVICES, + ViperKey: "export.services", } } @@ -96,8 +98,9 @@ func initOutputDirectoryOption() { "\nExample: 'pingcli-export'", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "export.outputDirectory", + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "export.outputDirectory", } } @@ -119,8 +122,9 @@ func initOverwriteOption() { Value: cobraValue, NoOptDefVal: "true", // Make this flag a boolean flag }, - Type: options.ENUM_BOOL, - ViperKey: "export.overwrite", + Sensitive: false, + Type: options.ENUM_BOOL, + ViperKey: "export.overwrite", } } @@ -140,7 +144,8 @@ func initPingOneEnvironmentIDOption() { Usage: "The ID of the PingOne environment to export. Must be a valid PingOne UUID.", Value: cobraValue, }, - Type: options.ENUM_UUID, - ViperKey: "export.pingone.environmentID", + Sensitive: false, + Type: options.ENUM_UUID, + ViperKey: "export.pingone.environmentID", } } diff --git a/internal/configuration/profiles/profiles.go b/internal/configuration/profiles/profiles.go index fe8801e5..3c375edd 100644 --- a/internal/configuration/profiles/profiles.go +++ b/internal/configuration/profiles/profiles.go @@ -16,6 +16,7 @@ func initDescriptionOption() { DefaultValue: new(customtypes.String), EnvVar: "", // No environment variable Flag: nil, // No flag + Sensitive: false, Type: options.ENUM_STRING, ViperKey: "description", } diff --git a/internal/configuration/request/request.go b/internal/configuration/request/request.go index 9b95e30b..38f35b4a 100644 --- a/internal/configuration/request/request.go +++ b/internal/configuration/request/request.go @@ -35,8 +35,9 @@ func initDataOption() { "\nExample: '@data.json'", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "", // No viper key + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "", // No viper key } } @@ -63,8 +64,9 @@ func initHTTPMethodOption() { ), Value: cobraValue, }, - Type: options.ENUM_REQUEST_HTTP_METHOD, - ViperKey: "", // No viper key + Sensitive: false, + Type: options.ENUM_REQUEST_HTTP_METHOD, + ViperKey: "", // No viper key } } @@ -91,8 +93,9 @@ func initServiceOption() { ), Value: cobraValue, }, - Type: options.ENUM_REQUEST_SERVICE, - ViperKey: "request.service", + Sensitive: false, + Type: options.ENUM_REQUEST_SERVICE, + ViperKey: "request.service", } } @@ -105,6 +108,7 @@ func initAccessTokenOption() { DefaultValue: &defaultValue, EnvVar: "", // No environment variable Flag: nil, + Sensitive: true, Type: options.ENUM_STRING, ViperKey: "request.accessToken", } @@ -119,6 +123,7 @@ func initAccessTokenExpiryOption() { DefaultValue: &defaultValue, EnvVar: "", // No environment variable Flag: nil, // No flag + Sensitive: false, Type: options.ENUM_INT, ViperKey: "request.accessTokenExpiry", } @@ -140,8 +145,8 @@ func initFailOption() { Usage: "Return non-zero exit code when HTTP custom request returns a failure status code.", Value: cobraValue, }, - - Type: options.ENUM_BOOL, - ViperKey: "request.fail", + Sensitive: false, + Type: options.ENUM_BOOL, + ViperKey: "request.fail", } } diff --git a/internal/configuration/root/root.go b/internal/configuration/root/root.go index a2ca4da6..0d7dc0d6 100644 --- a/internal/configuration/root/root.go +++ b/internal/configuration/root/root.go @@ -28,6 +28,7 @@ func initActiveProfileOption() { DefaultValue: &defaultValue, EnvVar: "", // No env var Flag: nil, // No flag + Sensitive: false, Type: options.ENUM_STRING, ViperKey: "activeProfile", } @@ -49,8 +50,9 @@ func initProfileOption() { Usage: "The name of a configuration profile to use.", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "", // No viper key + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "", // No viper key } } @@ -70,8 +72,9 @@ func initColorOption() { Value: cobraValue, NoOptDefVal: "true", // Make this flag a boolean flag }, - Type: options.ENUM_BOOL, - ViperKey: "noColor", + Sensitive: false, + Type: options.ENUM_BOOL, + ViperKey: "noColor", } } @@ -92,8 +95,9 @@ func initConfigOption() { "(default $HOME/.pingcli/config.yaml)", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "", // No viper key + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "", // No viper key } } @@ -119,8 +123,9 @@ func initOutputFormatOption() { ), Value: cobraValue, }, - Type: options.ENUM_OUTPUT_FORMAT, - ViperKey: "outputFormat", + Sensitive: false, + Type: options.ENUM_OUTPUT_FORMAT, + ViperKey: "outputFormat", } } diff --git a/internal/configuration/services/pingfederate.go b/internal/configuration/services/pingfederate.go index cba1a6d3..2aba87fc 100644 --- a/internal/configuration/services/pingfederate.go +++ b/internal/configuration/services/pingfederate.go @@ -42,8 +42,9 @@ func initHTTPSHostOption() { "\nExample: 'https://pingfederate-admin.bxretail.org'", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "service.pingfederate.httpsHost", + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "service.pingfederate.httpsHost", } } @@ -64,8 +65,9 @@ func initAdminAPIPathOption() { "(default /pf-admin-api/v1)", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "service.pingfederate.adminAPIPath", + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "service.pingfederate.adminAPIPath", } } @@ -88,8 +90,9 @@ func initXBypassExternalValidationHeaderOption() { Value: cobraValue, NoOptDefVal: "true", // Make this flag a boolean flag }, - Type: options.ENUM_BOOL, - ViperKey: "service.pingfederate.xBypassExternalValidationHeader", + Sensitive: false, + Type: options.ENUM_BOOL, + ViperKey: "service.pingfederate.xBypassExternalValidationHeader", } } @@ -112,8 +115,9 @@ func initCACertificatePemFilesOption() { "\nAccepts a comma-separated string to delimit multiple PEM files.", Value: cobraValue, }, - Type: options.ENUM_STRING_SLICE, - ViperKey: "service.pingfederate.caCertificatePemFiles", + Sensitive: false, + Type: options.ENUM_STRING_SLICE, + ViperKey: "service.pingfederate.caCertificatePemFiles", } } @@ -136,8 +140,9 @@ func initInsecureTrustAllTLSOption() { Value: cobraValue, NoOptDefVal: "true", // Make this flag a boolean flag }, - Type: options.ENUM_BOOL, - ViperKey: "service.pingfederate.insecureTrustAllTLS", + Sensitive: false, + Type: options.ENUM_BOOL, + ViperKey: "service.pingfederate.insecureTrustAllTLS", } } @@ -159,8 +164,9 @@ func initUsernameOption() { "\nExample: 'administrator'", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "service.pingfederate.authentication.basicAuth.username", + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "service.pingfederate.authentication.basicAuth.username", } } @@ -181,8 +187,9 @@ func initPasswordOption() { "authentication.", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "service.pingfederate.authentication.basicAuth.password", + Sensitive: true, + Type: options.ENUM_STRING, + ViperKey: "service.pingfederate.authentication.basicAuth.password", } } @@ -203,8 +210,9 @@ func initAccessTokenOption() { "custom OAuth 2.0 token method.", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "service.pingfederate.authentication.accessTokenAuth.accessToken", + Sensitive: true, + Type: options.ENUM_STRING, + ViperKey: "service.pingfederate.authentication.accessTokenAuth.accessToken", } } @@ -225,8 +233,9 @@ func initClientIDOption() { "the OAuth 2.0 client credentials grant type.", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "service.pingfederate.authentication.clientCredentialsAuth.clientID", + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "service.pingfederate.authentication.clientCredentialsAuth.clientID", } } @@ -247,8 +256,9 @@ func initClientSecretOption() { "using the OAuth 2.0 client credentials grant type.", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "service.pingfederate.authentication.clientCredentialsAuth.clientSecret", + Sensitive: true, + Type: options.ENUM_STRING, + ViperKey: "service.pingfederate.authentication.clientCredentialsAuth.clientSecret", } } @@ -269,8 +279,9 @@ func initTokenURLOption() { "the OAuth 2.0 client credentials grant type.", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "service.pingfederate.authentication.clientCredentialsAuth.tokenURL", + Sensitive: false, + Type: options.ENUM_STRING, + ViperKey: "service.pingfederate.authentication.clientCredentialsAuth.tokenURL", } } @@ -294,8 +305,9 @@ func initScopesOption() { "\nExample: 'openid,profile'", Value: cobraValue, }, - Type: options.ENUM_STRING_SLICE, - ViperKey: "service.pingfederate.authentication.clientCredentialsAuth.scopes", + Sensitive: false, + Type: options.ENUM_STRING_SLICE, + ViperKey: "service.pingfederate.authentication.clientCredentialsAuth.scopes", } } @@ -321,7 +333,8 @@ func initPingFederateAuthenticationTypeOption() { ), Value: cobraValue, }, - Type: options.ENUM_PINGFEDERATE_AUTH_TYPE, - ViperKey: "service.pingfederate.authentication.type", + Sensitive: false, + Type: options.ENUM_PINGFEDERATE_AUTH_TYPE, + ViperKey: "service.pingfederate.authentication.type", } } diff --git a/internal/configuration/services/pingone.go b/internal/configuration/services/pingone.go index 917d4ae9..eca3d5d3 100644 --- a/internal/configuration/services/pingone.go +++ b/internal/configuration/services/pingone.go @@ -34,8 +34,9 @@ func initAuthenticationWorkerClientIDOption() { Usage: "The worker client ID used to authenticate to the PingOne management API.", Value: cobraValue, }, - Type: options.ENUM_UUID, - ViperKey: "service.pingone.authentication.worker.clientID", + Sensitive: false, + Type: options.ENUM_UUID, + ViperKey: "service.pingone.authentication.worker.clientID", } } @@ -55,8 +56,9 @@ func initAuthenticationWorkerClientSecretOption() { Usage: "The worker client secret used to authenticate to the PingOne management API.", Value: cobraValue, }, - Type: options.ENUM_STRING, - ViperKey: "service.pingone.authentication.worker.clientSecret", + Sensitive: true, + Type: options.ENUM_STRING, + ViperKey: "service.pingone.authentication.worker.clientSecret", } } @@ -77,8 +79,9 @@ func initAuthenticationWorkerEnvironmentIDOption() { "the PingOne management API.", Value: cobraValue, }, - Type: options.ENUM_UUID, - ViperKey: "service.pingone.authentication.worker.environmentID", + Sensitive: false, + Type: options.ENUM_UUID, + ViperKey: "service.pingone.authentication.worker.environmentID", } } @@ -103,8 +106,9 @@ func initPingOneAuthenticationTypeOption() { ), Value: cobraValue, }, - Type: options.ENUM_PINGONE_AUTH_TYPE, - ViperKey: "service.pingone.authentication.type", + Sensitive: false, + Type: options.ENUM_PINGONE_AUTH_TYPE, + ViperKey: "service.pingone.authentication.type", } } @@ -130,7 +134,8 @@ func initRegionCodeOption() { ), Value: cobraValue, }, - Type: options.ENUM_PINGONE_REGION_CODE, - ViperKey: "service.pingone.regionCode", + Sensitive: false, + Type: options.ENUM_PINGONE_REGION_CODE, + ViperKey: "service.pingone.regionCode", } } diff --git a/internal/connector/pingone/sso/resources/pingone_schema_attribute_test.go b/internal/connector/pingone/sso/resources/pingone_schema_attribute_test.go index 8534e55f..b0343c23 100644 --- a/internal/connector/pingone/sso/resources/pingone_schema_attribute_test.go +++ b/internal/connector/pingone/sso/resources/pingone_schema_attribute_test.go @@ -161,6 +161,11 @@ func TestSchemaAttributeExport(t *testing.T) { ResourceName: "User_username", ResourceID: fmt.Sprintf("%s/ff3cb03d-4896-4d20-8612-f014c4048d01/77d3f22e-00ca-49d1-98a1-fc0ee48d2542", testutils.GetEnvironmentID()), }, + { + ResourceType: "pingone_schema_attribute", + ResourceName: "User_bypassMFA", + ResourceID: fmt.Sprintf("%s/ff3cb03d-4896-4d20-8612-f014c4048d01/355c50dc-0eb6-4c5b-ab36-2b3152e0534c", testutils.GetEnvironmentID()), + }, } testutils.ValidateImportBlocks(t, resource, &expectedImportBlocks) diff --git a/internal/profiles/viper.go b/internal/profiles/viper.go index 6a5dba11..bceee07b 100644 --- a/internal/profiles/viper.go +++ b/internal/profiles/viper.go @@ -361,7 +361,7 @@ func GetOptionValue(opt options.Option) (pFlagValue string, err error) { } // 3rd priority: viper value - viperValue, ok, err := viperValueFromOption(opt) + viperValue, ok, err := ViperValueFromOption(opt) if err != nil { return "", err } @@ -380,6 +380,16 @@ func GetOptionValue(opt options.Option) (pFlagValue string, err error) { return "", fmt.Errorf("failed to get option value: no value found: %v", opt) } +func MaskValue(value string) string { + if value == "" { + return "" + } + + // Mask all values to the same asterisk length + // providing no additional information about the value when logged. + return strings.Repeat("*", 8) +} + func cobraParamValueFromOption(opt options.Option) (value string, ok bool) { if opt.CobraParamValue != nil && opt.Flag.Changed { return opt.CobraParamValue.String(), true @@ -388,7 +398,7 @@ func cobraParamValueFromOption(opt options.Option) (value string, ok bool) { return "", false } -func viperValueFromOption(opt options.Option) (value string, ok bool, err error) { +func ViperValueFromOption(opt options.Option) (value string, ok bool, err error) { mainConfig := GetMainConfig() if opt.ViperKey != "" && mainConfig != nil { var (