diff --git a/CHANGELOG.md b/CHANGELOG.md index fe369bed..92639c84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - [#2295](https://github.com/oauth2-proxy/oauth2-proxy/pull/2295) Change base-image to [GoogleContainerTools/distroless](https://github.com/GoogleContainerTools/distroless) (@kvanzuijlen) - [#2356](https://github.com/oauth2-proxy/oauth2-proxy/pull/2356) Update go-jose dependency (@dasvh) - [#2357](https://github.com/oauth2-proxy/oauth2-proxy/pull/2357) Update ojg to latest release (@bitfehler) +- [#1922](https://github.com/oauth2-proxy/oauth2-proxy/pull/1922) Added support for env variables in the alpha struct (@hevans-dglcom) ## Release Highlights - 🐛 Several bugs have been squashed diff --git a/go.mod b/go.mod index 19f543e7..f6e32060 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( cloud.google.com/go/compute/metadata v0.2.3 github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb + github.com/a8m/envsubst v1.4.2 github.com/alicebob/miniredis/v2 v2.23.0 github.com/benbjohnson/clock v1.3.0 github.com/bitly/go-simplejson v0.5.1 diff --git a/go.sum b/go.sum index 893ef940..dbc85b6b 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/FZambia/sentinel v1.0.0 h1:KJ0ryjKTZk5WMp0dXvSdNqp3lFaW1fNFuEYfrkLOYIc= github.com/FZambia/sentinel v1.0.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg= +github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= diff --git a/pkg/apis/options/load.go b/pkg/apis/options/load.go index 4c752285..1f22dfbc 100644 --- a/pkg/apis/options/load.go +++ b/pkg/apis/options/load.go @@ -7,6 +7,7 @@ import ( "reflect" "strings" + "github.com/a8m/envsubst" "github.com/ghodss/yaml" "github.com/mitchellh/mapstructure" "github.com/spf13/pflag" @@ -140,25 +141,37 @@ func isUnexported(name string) bool { // LoadYAML will load a YAML based configuration file into the options interface provided. func LoadYAML(configFileName string, into interface{}) error { - v := viper.New() - v.SetConfigFile(configFileName) - v.SetConfigType("yaml") - v.SetTypeByDefaultValue(true) - - if configFileName == "" { - return errors.New("no configuration file provided") - } - - data, err := os.ReadFile(configFileName) + buffer, err := loadAndParseYaml(configFileName) if err != nil { - return fmt.Errorf("unable to load config file: %w", err) + return err } // UnmarshalStrict will return an error if the config includes options that are - // not mapped to felds of the into struct - if err := yaml.UnmarshalStrict(data, into, yaml.DisallowUnknownFields); err != nil { + // not mapped to fields of the into struct + if err := yaml.UnmarshalStrict(buffer, into, yaml.DisallowUnknownFields); err != nil { return fmt.Errorf("error unmarshalling config: %w", err) } return nil } + +// Performs the heavy lifting of the LoadYaml function +func loadAndParseYaml(configFileName string) ([]byte, error) { + if configFileName == "" { + return nil, errors.New("no configuration file provided") + } + + unparsedBuffer, err := os.ReadFile(configFileName) + if err != nil { + return nil, fmt.Errorf("unable to load config file: %w", err) + } + + // We now parse over the yaml with env substring, and fill in the ENV's + buffer, err := envsubst.Bytes(unparsedBuffer) + if err != nil { + return nil, fmt.Errorf("error in substituting env variables : %w", err) + } + + return buffer, nil + +} diff --git a/pkg/apis/options/load_test.go b/pkg/apis/options/load_test.go index c172893b..45a5616f 100644 --- a/pkg/apis/options/load_test.go +++ b/pkg/apis/options/load_test.go @@ -387,8 +387,13 @@ sub: DescribeTable("LoadYAML", func(in loadYAMLTableInput) { - var configFileName string + // Set the required environment variables before running the test + os.Setenv("TESTUSER", "Alice") + // Unset the environment variables after running the test + defer os.Unsetenv("TESTUSER") + + var configFileName string if in.configFile != nil { By("Creating a config file") configFile, err := os.CreateTemp("", "oauth2-proxy-test-config-file") @@ -467,6 +472,20 @@ sub: expectedOutput: &TestOptions{}, expectedErr: errors.New("error unmarshalling config: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go struct field TestOptions.StringSliceOption of type []string"), }), + Entry("with a config file containing environment variable references", loadYAMLTableInput{ + configFile: []byte("stringOption: ${TESTUSER}"), + input: &TestOptions{}, + expectedOutput: &TestOptions{ + StringOption: "Alice", + }, + }), + Entry("with a config file containing env variable references, with a fallback value", loadYAMLTableInput{ + configFile: []byte("stringOption: ${TESTUSER2=Bob}"), + input: &TestOptions{}, + expectedOutput: &TestOptions{ + StringOption: "Bob", + }, + }), ) })