fix(s3): wrap S3 secrets during config load

This commit is contained in:
Andrew Mayorov 2023-05-26 00:27:00 +03:00
parent 3d428a2e0e
commit 48858dee33
No known key found for this signature in database
GPG Key ID: 2837C62ACFBFED5D
5 changed files with 40 additions and 7 deletions

View File

@ -21,6 +21,10 @@
%% API:
-export([wrap/1, unwrap/1]).
-export_type([t/1]).
-opaque t(T) :: T | fun(() -> t(T)).
%%================================================================================
%% API funcions
%%================================================================================

View File

@ -44,7 +44,7 @@
-type profile_config() :: #{
bucket := string(),
access_key_id => string(),
secret_access_key => string(),
secret_access_key => emqx_secret:t(string()),
host := string(),
port := pos_integer(),
url_expire_time := pos_integer(),

View File

@ -60,7 +60,7 @@
acl := emqx_s3:acl() | undefined,
url_expire_time := pos_integer(),
access_key_id := string() | undefined,
secret_access_key := string() | undefined,
secret_access_key := emqx_secret:t(string()) | undefined,
http_pool := http_pool(),
pool_type := pool_type(),
request_timeout := timeout() | undefined,
@ -230,7 +230,7 @@ aws_config(#{
s3_bucket_after_host = true,
access_key_id = AccessKeyId,
secret_access_key = SecretAccessKey,
secret_access_key = emqx_secret:unwrap(SecretAccessKey),
http_client = request_fun(
HttpPool, PoolType, with_default(MaxRetries, ?DEFAULT_MAX_RETRIES)

View File

@ -34,11 +34,12 @@ fields(s3) ->
)},
{secret_access_key,
mk(
string(),
hoconsc:union([string(), function()]),
#{
desc => ?DESC("secret_access_key"),
required => false,
sensitive => true
sensitive => true,
converter => fun secret/2
}
)},
{bucket,
@ -142,6 +143,14 @@ desc(s3) ->
desc(transport_options) ->
"Options for the HTTP transport layer used by the S3 client".
secret(undefined, #{}) ->
undefined;
secret(Secret, #{make_serializable := true}) ->
unicode:characters_to_binary(emqx_secret:unwrap(Secret));
secret(Secret, #{}) ->
_ = is_binary(Secret) orelse throw({expected_type, string}),
emqx_secret:wrap(unicode:characters_to_list(Secret)).
translate(Conf) ->
translate(Conf, #{}).

View File

@ -49,7 +49,7 @@ t_full_config(_Config) ->
host := "s3.us-east-1.endpoint.com",
min_part_size := 10485760,
port := 443,
secret_access_key := "secret_access_key",
secret_access_key := Secret,
transport_options :=
#{
connect_timeout := 30000,
@ -74,7 +74,7 @@ t_full_config(_Config) ->
versions := ['tlsv1.2']
}
}
},
} when is_function(Secret),
emqx_s3_schema:translate(#{
<<"access_key_id">> => <<"access_key_id">>,
<<"secret_access_key">> => <<"secret_access_key">>,
@ -126,6 +126,26 @@ t_sensitive_config_hidden(_Config) ->
)
).
t_sensitive_config_no_leak(_Config) ->
?assertThrow(
{emqx_s3_schema, [
Error = #{
kind := validation_error,
path := "s3.secret_access_key",
reason := {expected_type, string}
}
]} when map_size(Error) == 3,
emqx_s3_schema:translate(
#{
<<"bucket">> => <<"bucket">>,
<<"host">> => <<"s3.us-east-1.endpoint.com">>,
<<"port">> => 443,
<<"access_key_id">> => <<"access_key_id">>,
<<"secret_access_key">> => #{<<"1">> => <<"secret_access_key">>}
}
)
).
t_invalid_limits(_Config) ->
?assertException(
throw,