From ead090d9ce1870b29aa28ae339fe6c280faa57a3 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Tue, 7 Nov 2023 12:22:44 -0700 Subject: [PATCH] core/config: add support for maps in environments --- config/constants.go | 1 + config/custom.go | 15 +++++++++++++++ config/options_test.go | 9 +++++++++ 3 files changed, 25 insertions(+) diff --git a/config/constants.go b/config/constants.go index 362ab380e..1020a17a3 100644 --- a/config/constants.go +++ b/config/constants.go @@ -39,4 +39,5 @@ var ViperPolicyHooks = viper.DecodeHook(mapstructure.ComposeDecodeHookFunc( decodeCodecTypeHookFunc(), decodePPLPolicyHookFunc(), decodeSANMatcherHookFunc(), + decodeStringToMapHookFunc(), )) diff --git a/config/custom.go b/config/custom.go index 1cd8a6902..c08359824 100644 --- a/config/custom.go +++ b/config/custom.go @@ -528,6 +528,21 @@ func decodeSANMatcherHookFunc() mapstructure.DecodeHookFunc { } } +func decodeStringToMapHookFunc() mapstructure.DecodeHookFunc { + return mapstructure.DecodeHookFuncValue(func(f, t reflect.Value) (any, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Map { + return f.Interface(), nil + } + + err := json.Unmarshal([]byte(f.Interface().(string)), t.Addr().Interface()) + if err != nil { + return nil, err + } + + return t.Interface(), nil + }) +} + // serializable converts mapstructure nested map into map[string]interface{} that is serializable to JSON func serializable(in interface{}) (interface{}, error) { switch typed := in.(type) { diff --git a/config/options_test.go b/config/options_test.go index bcd7021f3..a304aea5b 100644 --- a/config/options_test.go +++ b/config/options_test.go @@ -1263,6 +1263,15 @@ func TestOptions_RequestParams(t *testing.T) { } } +func TestOptions_RequestParamsFromEnv(t *testing.T) { + t.Setenv("IDP_REQUEST_PARAMS", `{"x":"y"}`) + + options, err := newOptionsFromConfig("") + if assert.NoError(t, err) { + assert.Equal(t, map[string]string{"x": "y"}, options.RequestParams) + } +} + func encodeCert(cert *tls.Certificate) []byte { return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Certificate[0]}) }