Merge pull request #9765 from zmstone/0115-add-password-converter

fix(schema): add password converter to ensure its binary() type
This commit is contained in:
Zaiming (Stone) Shi 2023-01-18 15:09:05 +01:00 committed by GitHub
commit 7abba17b25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 68 additions and 7 deletions

View File

@ -114,6 +114,7 @@
-export([namespace/0, roots/0, roots/1, fields/1, desc/1, tags/0]). -export([namespace/0, roots/0, roots/1, fields/1, desc/1, tags/0]).
-export([conf_get/2, conf_get/3, keys/2, filter/1]). -export([conf_get/2, conf_get/3, keys/2, filter/1]).
-export([server_ssl_opts_schema/2, client_ssl_opts_schema/1, ciphers_schema/1]). -export([server_ssl_opts_schema/2, client_ssl_opts_schema/1, ciphers_schema/1]).
-export([password_converter/2, bin_str_converter/2]).
-export([authz_fields/0]). -export([authz_fields/0]).
-export([sc/2, map/2]). -export([sc/2, map/2]).
@ -1510,7 +1511,9 @@ fields("sysmon_top") ->
#{ #{
mapping => "system_monitor.db_password", mapping => "system_monitor.db_password",
default => "system_monitor_password", default => "system_monitor_password",
desc => ?DESC(sysmon_top_db_password) desc => ?DESC(sysmon_top_db_password),
converter => fun password_converter/2,
sensitive => true
} }
)}, )},
{"db_name", {"db_name",
@ -1900,7 +1903,8 @@ common_ssl_opts_schema(Defaults) ->
required => false, required => false,
example => <<"">>, example => <<"">>,
format => <<"password">>, format => <<"password">>,
desc => ?DESC(common_ssl_opts_schema_password) desc => ?DESC(common_ssl_opts_schema_password),
converter => fun password_converter/2
} }
)}, )},
{"versions", {"versions",
@ -2068,6 +2072,21 @@ do_default_ciphers(_) ->
%% otherwise resolve default ciphers list at runtime %% otherwise resolve default ciphers list at runtime
[]. [].
password_converter(X, Opts) ->
bin_str_converter(X, Opts).
bin_str_converter(undefined, _) ->
undefined;
bin_str_converter(I, _) when is_integer(I) ->
integer_to_binary(I);
bin_str_converter(X, _) ->
try
iolist_to_binary(X)
catch
_:_ ->
throw("must_quote")
end.
authz_fields() -> authz_fields() ->
[ [
{"no_match", {"no_match",

View File

@ -465,3 +465,10 @@ converter_invalid_input_test() ->
?assertEqual(undefined, emqx_schema:convert_servers(undefined)), ?assertEqual(undefined, emqx_schema:convert_servers(undefined)),
%% 'foo: bar' is a valid HOCON value, but 'bar' is not a port number %% 'foo: bar' is a valid HOCON value, but 'bar' is not a port number
?assertThrow("bad_host_port", emqx_schema:convert_servers(#{foo => bar})). ?assertThrow("bad_host_port", emqx_schema:convert_servers(#{foo => bar})).
password_converter_test() ->
?assertEqual(undefined, emqx_schema:password_converter(undefined, #{})),
?assertEqual(<<"123">>, emqx_schema:password_converter(123, #{})),
?assertEqual(<<"123">>, emqx_schema:password_converter(<<"123">>, #{})),
?assertThrow("must_quote", emqx_schema:password_converter(foobar, #{})),
ok.

View File

@ -98,6 +98,7 @@ t_will_message_connection_denied(Config) when is_list(Config) ->
{will_payload, <<"should not be published">>} {will_payload, <<"should not be published">>}
]), ]),
Ref = monitor(process, Publisher), Ref = monitor(process, Publisher),
_ = unlink(Publisher),
{error, _} = emqtt:connect(Publisher), {error, _} = emqtt:connect(Publisher),
receive receive
{'DOWN', Ref, process, Publisher, Reason} -> {'DOWN', Ref, process, Publisher, Reason} ->

View File

@ -408,7 +408,8 @@ fields("node") ->
required => true, required => true,
'readOnly' => true, 'readOnly' => true,
sensitive => true, sensitive => true,
desc => ?DESC(node_cookie) desc => ?DESC(node_cookie),
converter => fun emqx_schema:password_converter/2
} }
)}, )},
{"process_limit", {"process_limit",

View File

@ -101,6 +101,7 @@ password(desc) -> ?DESC("password");
password(required) -> false; password(required) -> false;
password(format) -> <<"password">>; password(format) -> <<"password">>;
password(sensitive) -> true; password(sensitive) -> true;
password(converter) -> fun emqx_schema:password_converter/2;
password(_) -> undefined. password(_) -> undefined.
auto_reconnect(type) -> boolean(); auto_reconnect(type) -> boolean();

View File

@ -107,7 +107,8 @@ fields("server_configs") ->
#{ #{
format => <<"password">>, format => <<"password">>,
sensitive => true, sensitive => true,
desc => ?DESC("password") desc => ?DESC("password"),
converter => fun emqx_schema:password_converter/2
} }
)}, )},
{clean_start, {clean_start,

View File

@ -209,6 +209,7 @@ default_password(default) -> "public";
default_password(required) -> true; default_password(required) -> true;
default_password('readOnly') -> true; default_password('readOnly') -> true;
default_password(sensitive) -> true; default_password(sensitive) -> true;
default_password(converter) -> fun emqx_schema:password_converter/2;
default_password(desc) -> ?DESC(default_password); default_password(desc) -> ?DESC(default_password);
default_password(_) -> undefined. default_password(_) -> undefined.

View File

@ -380,7 +380,13 @@ fields(ssl_server_opts) ->
fields(clientinfo_override) -> fields(clientinfo_override) ->
[ [
{username, sc(binary(), #{desc => ?DESC(gateway_common_clientinfo_override_username)})}, {username, sc(binary(), #{desc => ?DESC(gateway_common_clientinfo_override_username)})},
{password, sc(binary(), #{desc => ?DESC(gateway_common_clientinfo_override_password)})}, {password,
sc(binary(), #{
desc => ?DESC(gateway_common_clientinfo_override_password),
sensitive => true,
format => <<"password">>,
converter => fun emqx_schema:password_converter/2
})},
{clientid, sc(binary(), #{desc => ?DESC(gateway_common_clientinfo_override_clientid)})} {clientid, sc(binary(), #{desc => ?DESC(gateway_common_clientinfo_override_clientid)})}
]; ];
fields(lwm2m_translators) -> fields(lwm2m_translators) ->

View File

@ -0,0 +1,6 @@
Parse decimals as password from environment variable overrides correctly.
Prior to this change, config values for passwords are not allowed to be decimals.
e.g. `EMQX_FOOBAR__PASSWORD=12344` or `emqx.foobar.password=1234`
would result in a type check error, unless quoted as:
`EMQX_FOOBAR__PASSWORD='"12344"'` or `emqx.foobar.password="1234"`.
After this fix, the value does not have to be quoted.

View File

@ -0,0 +1,7 @@
允许使用纯数字作为密码配置。
在此修复前,密码的配置必须是字符串,使用纯数字时,会报类型检查错误。
例如,`EMQX_FOOBAR__PASSWORD=12344` 或 `emqx.foobar.password=1234` 会出错,
必须用引把值括起来才行:
`EMQX_FOOBAR__PASSWORD='"12344"'``emqx.foobar.password="1234"`
修复后可以不使用引号。在环境变量重载中使用更加方便。

View File

@ -116,7 +116,12 @@ fields(auth_username_password) ->
})}, })},
{username, mk(binary(), #{required => true, desc => ?DESC(auth_sasl_username)})}, {username, mk(binary(), #{required => true, desc => ?DESC(auth_sasl_username)})},
{password, {password,
mk(binary(), #{required => true, sensitive => true, desc => ?DESC(auth_sasl_password)})} mk(binary(), #{
required => true,
sensitive => true,
desc => ?DESC(auth_sasl_password),
converter => fun emqx_schema:password_converter/2
})}
]; ];
fields(auth_gssapi_kerberos) -> fields(auth_gssapi_kerberos) ->
[ [

View File

@ -157,7 +157,13 @@ fields(influxdb_api_v1) ->
[ [
{database, mk(binary(), #{required => true, desc => ?DESC("database")})}, {database, mk(binary(), #{required => true, desc => ?DESC("database")})},
{username, mk(binary(), #{desc => ?DESC("username")})}, {username, mk(binary(), #{desc => ?DESC("username")})},
{password, mk(binary(), #{desc => ?DESC("password"), format => <<"password">>})} {password,
mk(binary(), #{
desc => ?DESC("password"),
format => <<"password">>,
sensitive => true,
converter => fun emqx_schema:password_converter/2
})}
] ++ emqx_connector_schema_lib:ssl_fields(); ] ++ emqx_connector_schema_lib:ssl_fields();
fields(influxdb_api_v2) -> fields(influxdb_api_v2) ->
fields(common) ++ fields(common) ++