Skip to content
Permalink
Browse files
Implement is_sensitive/2 using configurable application env
If it exists, consult a file to configure application env. If
`sensitive` env key is found therein, use it to determine which values
to redact from log entries. The value of the `sensitive` key should be
a dict of the form:
```
#{
    Section1 => [Field1, Field2, ...],
    Section2 => all
}
```
where `Section`s are strings that define sections which contain
sensitive fields, and `Field`s are strings. The atom `all` indicates
all fields for that section are sensitive. A typical configuration
might look like:
```
#{
    "admins" => all,
    "replicator" => ["password"]
}
```
meaning that all values in the `[admins]` section, and the `password`
value in the `[replicator]` section will be redacted from the logs.
  • Loading branch information
jaydoane committed Feb 23, 2021
1 parent ff74353 commit 6937283083c6835339ce226b00d6ecee25a7f525
Showing 2 changed files with 33 additions and 3 deletions.
@@ -10,6 +10,15 @@
% License for the specific language governing permissions and limitations under
% the License.

ConfigPath = filename:join([os:getenv("COUCHDB_APPS_CONFIG_DIR"), "config.config"]),
AppEnv = case filelib:is_file(ConfigPath) of
true ->
{ok, Result} = file:consult(ConfigPath),
Result;
false ->
[]
end.

{application, config, [
{description, "INI file configuration system for Apache CouchDB"},
{vsn, git},
@@ -18,5 +27,6 @@
config_event
]},
{applications, [kernel, stdlib]},
{mod, {config_app, []}}
{mod, {config_app, []}},
{env, AppEnv}
]}.
@@ -40,6 +40,8 @@
-export([init/1, terminate/2, code_change/3]).
-export([handle_call/3, handle_cast/2, handle_info/2]).

-export([is_sensitive/2]).

-define(FEATURES, "features").

-define(TIMEOUT, 30000).
@@ -247,7 +249,7 @@ handle_call(all, _From, Config) ->
handle_call({set, Sec, Key, Val, Opts}, _From, Config) ->
Persist = maps:get(persist, Opts, true),
Reason = maps:get(reason, Opts, nil),
IsSensitive = maps:get(sensitive, Opts, false),
IsSensitive = is_sensitive(Sec, Key),
case validate_config_update(Sec, Key, Val) of
{error, ValidationError} when IsSensitive ->
couch_log:error("~p: [~s] ~s = '****' rejected for reason ~p",
@@ -322,7 +324,16 @@ handle_call(reload, _From, Config) ->
true ->
ok;
false ->
couch_log:notice("Reload detected config change ~s.~s = ~p", [Sec, Key, V]),
case is_sensitive(Sec, Key) of
false ->
couch_log:notice(
"Reload detected config change ~s.~s = ~p",
[Sec, Key, V]);
true ->
couch_log:notice(
"Reload detected config change ~s.~s = '****'",
[Sec, Key])
end,
Event = {config_change, Sec, Key, V, true},
gen_event:sync_notify(config_event, Event)
end
@@ -356,6 +367,15 @@ code_change(_OldVsn, State, _Extra) ->
{ok, State}.


is_sensitive(Section, Key) ->
Sensitive = application:get_env(config, sensitive, #{}),
case maps:get(Section, Sensitive, false) of
all -> true;
Fields when is_list(Fields) -> lists:member(Key, Fields);
_ -> false
end.


parse_ini_file(IniFile) ->
IniFilename = config_util:abs_pathname(IniFile),
IniBin =

0 comments on commit 6937283

Please sign in to comment.