Skip to content

Commit

Permalink
Add a Secret type to register secret settings
Browse files Browse the repository at this point in the history
this adds a Secret type which is just a string but can be used  to
register a setting as a Secret setting, by using this type for the
default empty value of the config

this adds a new private field 'isSecret' to 'Setting' struct which
is used by AddSetting to mark a Setting as secret

based on this field it is decided which storage is used to persist
or fetch the config setting
  • Loading branch information
anjannath committed Sep 29, 2022
1 parent 7a5d10a commit f956555
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 9 deletions.
59 changes: 50 additions & 9 deletions pkg/crc/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand All @@ -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)
Expand All @@ -94,24 +95,34 @@ 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
}

// 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
}

Expand All @@ -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
}
Expand Down Expand Up @@ -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,
Expand All @@ -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
}
6 changes: 6 additions & 0 deletions pkg/crc/config/secret_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
66 changes: 66 additions & 0 deletions pkg/crc/config/secret_config_test.go
Original file line number Diff line number Diff line change
@@ -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))
}
1 change: 1 addition & 0 deletions pkg/crc/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Setting struct {
defaultValue interface{}
validationFn ValidationFnType
callbackFn SetFn
isSecret bool
Help string
}

Expand Down

0 comments on commit f956555

Please sign in to comment.