Skip to content

Instantly share code, notes, and snippets.

@stoyle
Last active Sep 30, 2020
Embed
What would you like to do?
defmodule Coruscant.ConfigLogger do
require Logger
@secret_matcher ~r/key|secret|salt|encryption|password|connection_string|creds/
defp secrets_masker(k, v) do
s =
if is_atom(k) do
Atom.to_string(k)
else
k
end
if is_binary(v) &&
is_binary(s) &&
Regex.match?(@secret_matcher, s) do
{k, ((v || "") |> String.first()) <> "*****"}
else
{k, v}
end
end
defp deep_transform(data) do
cond do
is_tuple(data) && tuple_size(data) == 2 ->
{k, v} = data
if is_binary(v) do
{k, secrets_masker(k, v)}
else
{k, deep_transform(v)}
end
is_struct(data) && data.__struct__ in [Regex, DateTime, NaiveDateTime, Time] ->
data
is_struct(data) ->
type = data.__struct__
data
|> Map.drop([:__struct__])
|> map_transform()
|> Map.put(:__struct__, type)
is_map(data) ->
map_transform(data)
is_map(data) || is_struct(data) ->
Enum.reduce(data, %{}, fn {k, v}, acc ->
if is_binary(v) do
Map.put(acc, k, secrets_masker(k, v))
else
Map.put(acc, k, deep_transform(v))
end
end)
is_list(data) ->
Enum.map(data, fn value -> deep_transform(value) end)
true ->
data
end
end
defp map_transform(map),
do:
Enum.reduce(map, %{}, fn {k, v}, acc ->
if is_binary(v) do
Map.put(acc, k, secrets_masker(k, v))
else
Map.put(acc, k, deep_transform(v))
end
end)
def log_all_applicaion_config(my_app) do
try do
conf =
([{my_app, "Top level"}] ++ Application.started_applications())
|> Enum.map(&elem(&1, 0))
|> Enum.map(fn app -> {app, Application.get_all_env(app)} end)
|> Enum.reject(fn {_app, conf} -> Enum.empty?(conf) end)
|> Enum.map(fn {app, v} -> {app, deep_transform(v)} end)
|> inspect(pretty: true)
Logger.info("My configuration is #{conf}")
rescue
ex ->
Logger.warn("Problem logging out config #{Exception.format(:error, ex, __STACKTRACE__)}")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment