I’m getting ready to deploy my first Elixir app, and it manages very sensitive data. I plan to use Distillery for releases, and I’m clear on how it manages configuration. What I’m not sure of is the best way to handle secrets like API keys and the Ecto Repo DB credentials. Here are a few approaches I’ve considered:
Use config.exs or prod.exs: This isn’t compatible with Distillery because the values would be evaluated at compile time. There is also the risk that these types of files might be checked into a Git repository accidentally.
Use environment variables as discussed on the plataformatec blog and promoted by the 12-Factor App: This approach is not universally embraced. The overall consensus of this discussion seems to be that environment variables were never intended to be private, and they may be inadvertently exposed. Many argue that files are inherently more secure because access to them can be controlled and reasoned about through permissions, which is lacking for the environment.
Store the configuration in a file located away from the code, such as in
/etc. This seemed appealing, until I released that I wouldn’t be able to lock down the permissions very much. The user that the release is running as will need read access, and isn’t that the riskiest user to have access?
Encrypt the secrets using something like AWS KMS. On app startup, send an HTTP request to decrypt them and store them only in memory. Yes, we still need to store the AWS credentials somehow, but at least we can restrict access by IP, and all KMS requests are logged so we can configure some type of alert every time a decryption call is made. But is this even possible? Would I then set the env manually using Application.put_env? Would I need a separate app to handle configuration decryption and loading before the target app is executing? Do I need to be worried about this warning in the docs?
Do not use the functions in this module for directly accessing or modifying the environment of other applications (as it may lead to inconsistent data in the application environment).
I thought maybe I could use the transforms feature is Conform to handle decryption, but it looks like the output of this tool is an erlang
sys.configfile that gets written to disk. That doesn’t solve the problem.
I’m sure this must be a solved problem. How are others dealing with this? Am I just being unreasonably paranoid?