Current section

Files

Jump to
elixir_structure_manager priv templates adapters secrets_manager secret_adapter.ex
Raw

priv/templates/adapters/secrets_manager/secret_adapter.ex

defmodule {app}.Adapters.Secrets.SecretManagerAdapter do
use GenServer
alias {app}.Config.ConfigHolder
alias {app}.Utils.DataTypeUtils
@compile if Mix.env == :test, do: :export_all
@moduledoc """
Provides functions for handle secrets from AWS
"""
def start_link(async_init) do
GenServer.start_link(__MODULE__, async_init, name: __MODULE__)
end
def init(true = _async_init) do
create_ets()
send(self(), :get_secret)
{:ok, nil}
end
def init(_async_init) do
create_ets()
{:ok, get_initial_secret()}
end
defp create_ets do
:ets.new(:secret_manager_adapter, [:named_table, read_concurrency: true])
end
def handle_info(:get_secret, _args) do
{:noreply, get_initial_secret()}
end
defp get_initial_secret() do
if Mix.env() == :prod do
secret_name = ConfigHolder.conf.secret_name
region = ConfigHolder.conf.region
secret = get_secret_value(secret_name, region)
|> Poison.decode!
|> DataTypeUtils.normalize
:ets.insert(:secret_manager_adapter, {:secret, secret})
secret
end
end
def get_secret() do
if Mix.env() == :prod do
case :ets.lookup(:secret_manager_adapter, :secret) do
[{_, secret}] -> secret
_ -> GenServer.call(__MODULE__, :get_secret)
end
else
ConfigHolder.conf
end
end
def handle_call(:get_secret, _from, state) do
{:reply, state, state}
end
defp get_secret_value(secret_name, region) do
ExAws.SecretsManager.get_secret_value(secret_name)
|> ExAws.request(region: region)
|> case do
{:ok, %{"SecretString" => secret_string}} -> secret_string
{code, rs} -> {code, rs}
no_expected -> {:error, no_expected}
end
end
end