ryanzidago
Why is it recommended to use a GenServer when reading the Cloak encryption key as an env var?
Why is it recommended (from the official Cloak doc) to do this:
# Assumes that you have a CLOAK_KEY environment variable containing a key in
# Base64 encoding.
#
# export CLOAK_KEY="A7x+qcFD9yeRfl3GohiOFZM5bNCdHNu27B0Ozv8X4dE="
defmodule MyApp.Vault do
use Cloak.Vault, otp_app: :my_app
@impl GenServer
def init(config) do
config =
Keyword.put(config, :ciphers, [
default: {
Cloak.Ciphers.AES.GCM,
tag: "AES.GCM.V1",
key: decode_env!("CLOAK_KEY"),
iv_length: 12
}
])
{:ok, config}
end
defp decode_env!(var) do
var
|> System.get_env()
|> Base.decode64!()
end
end
instead of this:
config :my_app, MyApp.Vault,
ciphers: [
default: {
Cloak.Ciphers.AES.GCM,
tag: "AES.GCM.V1",
# Reading the encryption key from an env var directly in the config
key: Base.decode64!(System.fetch_env!("CLOAK_ENCRYPTION_KEY")),
# In AES.GCM, it is important to specify 12-byte IV length for
# interoperability with other encryption software. See this GitHub
# issue for more details:
# https://github.com/danielberkompas/cloak/issues/93
#
# In Cloak 2.0, this will be the default iv length for AES.GCM.
iv_length: 12
}
]
Reading the encryption key from an env var directly in the config allows me to very quickly have different configs (and different encrypt. keys) for different Mix.env/0.
I can embed the env var into the test.exs and dev.exs file doing like so:
System.put_env("CLOAK_ENCRYPTION_KEY", "some_encryption_key")
But it feels weird + I still don’t understand why the official doc suggests creating a GenServer.
Marked As Solved
al2o3cr
Saying use Cloak.Vault already is making a GenServer, adding the init function is just customizing what happens at startup:
The main reason to do it there vs in prod.exs etc is timing: if you’re building a release, prod.exs gets evaluated at compile time when the release is built rather than when the released application boots.
Those instructions predate the introduction of runtime config in runtime.exs (in 1.11) by several years, which explains why they don’t suggest it.
Yet another way to handle this config would be to pass it along at the supervisor level, similar to how libraries like Finch do it, so instead of adding just MyApp.Vault you’d add {MyApp.Vault, [ciphers: ...etc...]}







