Configuration management is such a fun problem to solve! You can use libraries like dynaconf (Python) or viper (Go) and they’re super fancy and will probably provide everything you want (and a bit more).

Today I wanted to code, though. For a pet project, I wanted something as simple as: well, try to get this configuration from env vars, and try to look in a secret manager for those you can’t find. I wanted no dependencies for this small task, for this small project, and for those starting with configuration management, it might be a fun way to understand the power those libraries can give you.

In this particular project, I was using Go!

So at first, I made sure I had a structure defining what I needed for my app.

199
200
201
202
203
type Config struct {
	NonSecretVariable                   string
	SecretVariable                      string
	VeryImportantSecretVariable         string
}

This is a struct that should know how to validate itself. It returns an error if it has a value that is null (or invalid, if you wanna check that, be my guest) on a very important value.

199
200
201
202
203
204
func (c *Config) Validate() error {
	if c.VeryImportantSecretVariable == "" {
		return errors.New("VeryImportantSecretVariable must be provided")
	}
	return nil
}

Then, to populate this structure, I had a chunk of code that ended up pretty elegant:

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
func GetConfig() *Config {
	c := new(Config)
	ep := new(EnvironmentVariablesConfigurationProvider)
	c = ep.PopulateConfig(c)
	if err := c.Validate(); err == nil {
		return c
	}

	gsmp := new(GoogleSecretManagerConfigurationProvider)
	c = gsmp.PopulateConfig(c)
	if err := c.Validate(); err != nil {
		panic(err)
	}
	return c
}

In the above code I access two implementations of a ConfigurationProvider interface. If the first one doesn’t give me all variables I want, then I go for the second one. In my case, I was using Google Secret Manager to store a secret, but you can use Azure Key Vault, Hashicorp’s Vault, or, y’know, pretty much anything that floats your boat.

The implementation of the providers is not gonna be covered here because they can be pretty length (and in all honesty, I don’t wanna code a configuration management library), but I’d like to bring up the importance of storing your secrets more securely and show how easy it can be to achieve that without having to add a external dependency.

That’s all for now! :D