diff --git a/pkg/crc/config/config.go b/pkg/crc/config/config.go index dd0c89fe34..42ac54d768 100644 --- a/pkg/crc/config/config.go +++ b/pkg/crc/config/config.go @@ -57,6 +57,7 @@ func (c *Config) AddSetting(name string, defValue interface{}, validationFn Vali defaultValue: defValue, validationFn: validationFn, callbackFn: callbackFn, + isSecret: isUnderlyingTypeSecret(defValue), Help: help, } } @@ -81,7 +82,7 @@ func (c *Config) Set(key string, value interface{}) (string, error) { if err != nil { return "", fmt.Errorf(invalidProp, value, key, err) } - case string: + case string, Secret: castValue = cast.ToString(value) case bool: castValue, err = cast.ToBoolE(value) @@ -94,8 +95,14 @@ func (c *Config) Set(key string, value interface{}) (string, error) { return "", fmt.Errorf(invalidType, value, key) } - if err := c.storage.Set(key, castValue); err != nil { - return "", err + if setting.isSecret { + if err := c.secretStorage.Set(key, castValue); err != nil { + return "", err + } + } else { + if err := c.storage.Set(key, castValue); err != nil { + return "", err + } } return c.settingsByName[key].callbackFn(key, castValue), nil @@ -103,15 +110,19 @@ func (c *Config) Set(key string, value interface{}) (string, error) { // Unset unsets a given config key func (c *Config) Unset(key string) (string, error) { - _, ok := c.settingsByName[key] + setting, ok := c.settingsByName[key] if !ok { return "", fmt.Errorf(configPropDoesntExistMsg, key) } - - if err := c.storage.Unset(key); err != nil { - return "", err + if setting.isSecret { + if err := c.secretStorage.Unset(key); err != nil { + return "", err + } + } else { + if err := c.storage.Unset(key); err != nil { + return "", err + } } - return fmt.Sprintf("Successfully unset configuration property '%s'", key), nil } @@ -122,7 +133,12 @@ func (c *Config) Get(key string) SettingValue { Invalid: true, } } - value := c.storage.Get(key) + var value interface{} + if setting.isSecret { + value = c.secretStorage.Get(key) + } else { + value = c.storage.Get(key) + } if value == nil { value = setting.defaultValue } @@ -151,6 +167,13 @@ func (c *Config) Get(key string) SettingValue { Invalid: true, } } + case Secret: + value, err = toSecret(value) + if err != nil { + return SettingValue{ + Invalid: true, + } + } default: return SettingValue{ Invalid: true, @@ -161,3 +184,21 @@ func (c *Config) Get(key string) SettingValue { IsDefault: reflect.DeepEqual(setting.defaultValue, value), } } + +func toSecret(value interface{}) (Secret, error) { + if isUnderlyingTypeSecret(value) { + return value.(Secret), nil + } + v, err := cast.ToStringE(value) + if err != nil { + return Secret(""), err + } + return Secret(v), nil +} + +func isUnderlyingTypeSecret(value interface{}) bool { + if _, ok := value.(Secret); ok { + return true + } + return false +} diff --git a/pkg/crc/config/secret_config.go b/pkg/crc/config/secret_config.go index 701a405b1f..444365b80e 100644 --- a/pkg/crc/config/secret_config.go +++ b/pkg/crc/config/secret_config.go @@ -13,6 +13,12 @@ const secretServiceName = "crc" var ErrSecretsNotAccessible = errors.New("secret store is not accessible") +type Secret string + +func (s Secret) String() string { + return string(s) +} + type SecretStorage struct { secretService string storeAccessible bool diff --git a/pkg/crc/config/secret_config_test.go b/pkg/crc/config/secret_config_test.go new file mode 100644 index 0000000000..217f359fa1 --- /dev/null +++ b/pkg/crc/config/secret_config_test.go @@ -0,0 +1,66 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const ( + password = "password" + secret = "secret" +) + +func newTestConfigSecret() (*Config, error) { + cfg := New(NewEmptyInMemoryStorage(), NewEmptyInMemorySecretStorage()) + + cfg.AddSetting(password, Secret(""), ValidateString, SuccessfullyApplied, "") + cfg.AddSetting(secret, Secret("apples"), ValidateString, SuccessfullyApplied, "") + return cfg, nil +} + +func TestGetSecret(t *testing.T) { + cfg, err := newTestConfigSecret() + require.NoError(t, err) + + assert.Equal(t, SettingValue{ + Value: Secret("apples"), + IsDefault: true, + }, cfg.Get(secret)) +} + +func TestSecretConfigUnknown(t *testing.T) { + cfg, err := newTestConfigSecret() + require.NoError(t, err) + + assert.Equal(t, SettingValue{ + Invalid: true, + }, cfg.Get("baz")) +} + +func TestSecretConfigSetAndGet(t *testing.T) { + cfg, err := newTestConfigSecret() + require.NoError(t, err) + + _, err = cfg.Set(password, "pass123") + assert.NoError(t, err) + + assert.Equal(t, SettingValue{ + Value: Secret("pass123"), + IsDefault: false, + }, cfg.Get(password)) +} + +func TestSecretConfigUnsetAndGet(t *testing.T) { + cfg, err := newTestConfigSecret() + require.NoError(t, err) + + _, err = cfg.Unset(secret) + assert.NoError(t, err) + + assert.Equal(t, SettingValue{ + Value: Secret("apples"), + IsDefault: true, + }, cfg.Get(secret)) +} diff --git a/pkg/crc/config/types.go b/pkg/crc/config/types.go index 8b0b36a882..59b5c645b4 100644 --- a/pkg/crc/config/types.go +++ b/pkg/crc/config/types.go @@ -18,6 +18,7 @@ type Setting struct { defaultValue interface{} validationFn ValidationFnType callbackFn SetFn + isSecret bool Help string }