fix(authn): api required fields

This commit is contained in:
JimMoen 2022-04-11 15:41:27 +08:00
parent cf671f10e7
commit 88c98bb310
12 changed files with 74 additions and 49 deletions

View File

@ -29,14 +29,14 @@
providers() -> providers() ->
[ [
{{'password_based', 'built_in_database'}, emqx_authn_mnesia}, {{password_based, built_in_database}, emqx_authn_mnesia},
{{'password_based', mysql}, emqx_authn_mysql}, {{password_based, mysql}, emqx_authn_mysql},
{{'password_based', postgresql}, emqx_authn_pgsql}, {{password_based, postgresql}, emqx_authn_pgsql},
{{'password_based', mongodb}, emqx_authn_mongodb}, {{password_based, mongodb}, emqx_authn_mongodb},
{{'password_based', redis}, emqx_authn_redis}, {{password_based, redis}, emqx_authn_redis},
{{'password_based', 'http'}, emqx_authn_http}, {{password_based, http}, emqx_authn_http},
{jwt, emqx_authn_jwt}, {jwt, emqx_authn_jwt},
{{scram, 'built_in_database'}, emqx_enhanced_authn_scram_mnesia} {{scram, built_in_database}, emqx_enhanced_authn_scram_mnesia}
]. ].
check_configs(C) when is_map(C) -> check_configs(C) when is_map(C) ->

View File

@ -128,21 +128,22 @@ roots() ->
fields(request_user_create) -> fields(request_user_create) ->
[ [
{user_id, binary()} {user_id, mk(binary(), #{required => true})}
| fields(request_user_update) | fields(request_user_update)
]; ];
fields(request_user_update) -> fields(request_user_update) ->
[ [
{password, binary()}, {password, mk(binary(), #{required => true})},
{is_superuser, mk(boolean(), #{default => false, required => false})} {is_superuser, mk(boolean(), #{default => false, required => false})}
]; ];
fields(request_move) -> fields(request_move) ->
[{position, binary()}]; [{position, mk(binary(), #{required => true})}];
fields(request_import_users) -> fields(request_import_users) ->
[{filename, binary()}]; %% TODO: add file update
[{filename, mk(binary(), #{required => true})}];
fields(response_user) -> fields(response_user) ->
[ [
{user_id, binary()}, {user_id, mk(binary(), #{required => true})},
{is_superuser, mk(boolean(), #{default => false, required => false})} {is_superuser, mk(boolean(), #{default => false, required => false})}
]; ];
fields(response_users) -> fields(response_users) ->
@ -425,10 +426,8 @@ schema("/authentication/:id/users") ->
description => <<"List users in authenticator in global authentication chain">>, description => <<"List users in authenticator in global authentication chain">>,
parameters => [ parameters => [
param_auth_id(), param_auth_id(),
{page, ref(emqx_dashboard_swagger, page),
mk(pos_integer(), #{in => query, desc => <<"Page Index">>, required => false})}, ref(emqx_dashboard_swagger, limit),
{limit,
mk(pos_integer(), #{in => query, desc => <<"Page Limit">>, required => false})},
{like_username, {like_username,
mk(binary(), #{ mk(binary(), #{
in => query, in => query,
@ -477,10 +476,8 @@ schema("/listeners/:listener_id/authentication/:id/users") ->
parameters => [ parameters => [
param_listener_id(), param_listener_id(),
param_auth_id(), param_auth_id(),
{page, ref(emqx_dashboard_swagger, page),
mk(pos_integer(), #{in => query, desc => <<"Page Index">>, required => false})}, ref(emqx_dashboard_swagger, limit)
{limit,
mk(pos_integer(), #{in => query, desc => <<"Page Limit">>, required => false})}
], ],
responses => #{ responses => #{
200 => emqx_dashboard_swagger:schema_with_example( 200 => emqx_dashboard_swagger:schema_with_example(
@ -581,7 +578,8 @@ param_auth_id() ->
id, id,
mk(binary(), #{ mk(binary(), #{
in => path, in => path,
desc => <<"Authenticator ID">> desc => <<"Authenticator ID">>,
required => true
}) })
}. }.
@ -591,6 +589,7 @@ param_listener_id() ->
mk(binary(), #{ mk(binary(), #{
in => path, in => path,
desc => <<"Listener ID">>, desc => <<"Listener ID">>,
required => true,
example => emqx_listeners:id_example() example => emqx_listeners:id_example()
}) })
}. }.
@ -1177,6 +1176,7 @@ update_config(Path, ConfigRequest) ->
get_raw_config_with_defaults(ConfKeyPath) -> get_raw_config_with_defaults(ConfKeyPath) ->
NConfKeyPath = [atom_to_binary(Key, utf8) || Key <- ConfKeyPath], NConfKeyPath = [atom_to_binary(Key, utf8) || Key <- ConfKeyPath],
RawConfig = emqx_map_lib:deep_get(NConfKeyPath, emqx_config:get_raw([]), []), RawConfig = emqx_map_lib:deep_get(NConfKeyPath, emqx_config:get_raw([]), []),
%% TODO: check plain unexcepted
ensure_list(fill_defaults(RawConfig)). ensure_list(fill_defaults(RawConfig)).
find_config(AuthenticatorID, AuthenticatorsConfig) -> find_config(AuthenticatorID, AuthenticatorsConfig) ->

View File

@ -68,21 +68,31 @@ roots() -> [pbkdf2, bcrypt, bcrypt_rw, other_algorithms].
fields(bcrypt_rw) -> fields(bcrypt_rw) ->
fields(bcrypt) ++ fields(bcrypt) ++
[{salt_rounds, fun salt_rounds/1}]; [
{salt_rounds,
sc(
integer(),
#{
default => 10,
example => 10,
desc => "Salt rounds for BCRYPT password generation."
}
)}
];
fields(bcrypt) -> fields(bcrypt) ->
[{name, sc(bcrypt, #{desc => "BCRYPT password hashing."})}]; [{name, sc(bcrypt, #{required => true, desc => "BCRYPT password hashing."})}];
fields(pbkdf2) -> fields(pbkdf2) ->
[ [
{name, sc(pbkdf2, #{desc => "PBKDF2 password hashing."})}, {name, sc(pbkdf2, #{required => true, desc => "PBKDF2 password hashing."})},
{mac_fun, {mac_fun,
sc( sc(
hoconsc:enum([md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512]), hoconsc:enum([md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512]),
#{desc => "Specifies mac_fun for PBKDF2 hashing algorithm."} #{required => true, desc => "Specifies mac_fun for PBKDF2 hashing algorithm."}
)}, )},
{iterations, {iterations,
sc( sc(
integer(), integer(),
#{desc => "Iteration count for PBKDF2 hashing algorithm."} #{required => true, desc => "Iteration count for PBKDF2 hashing algorithm."}
)}, )},
{dk_length, fun dk_length/1} {dk_length, fun dk_length/1}
]; ];
@ -91,10 +101,7 @@ fields(other_algorithms) ->
{name, {name,
sc( sc(
hoconsc:enum([plain, md5, sha, sha256, sha512]), hoconsc:enum([plain, md5, sha, sha256, sha512]),
#{ #{required => true, desc => "Simple password hashing algorithm."}
desc =>
"Simple password hashing algorithm."
}
)}, )},
{salt_position, fun salt_position/1} {salt_position, fun salt_position/1}
]. ].
@ -115,11 +122,6 @@ salt_position(default) -> prefix;
salt_position(desc) -> "Salt position for PLAIN, MD5, SHA, SHA256 and SHA512 algorithms."; salt_position(desc) -> "Salt position for PLAIN, MD5, SHA, SHA256 and SHA512 algorithms.";
salt_position(_) -> undefined. salt_position(_) -> undefined.
salt_rounds(type) -> integer();
salt_rounds(default) -> 10;
salt_rounds(desc) -> "Salt rounds for BCRYPT password generation.";
salt_rounds(_) -> undefined.
dk_length(type) -> dk_length(type) ->
integer(); integer();
dk_length(required) -> dk_length(required) ->
@ -130,6 +132,7 @@ dk_length(desc) ->
dk_length(_) -> dk_length(_) ->
undefined. undefined.
%% for simple_authn/emqx_authn_mnesia
type_rw(type) -> type_rw(type) ->
hoconsc:union(rw_refs()); hoconsc:union(rw_refs());
type_rw(default) -> type_rw(default) ->
@ -139,6 +142,7 @@ type_rw(desc) ->
type_rw(_) -> type_rw(_) ->
undefined. undefined.
%% for other authn resources
type_ro(type) -> type_ro(type) ->
hoconsc:union(ro_refs()); hoconsc:union(ro_refs());
type_ro(default) -> type_ro(default) ->

View File

@ -57,12 +57,12 @@ roots() ->
fields(get) -> fields(get) ->
[ [
{method, #{type => get, default => post, desc => "HTTP method."}}, {method, #{type => get, required => true, default => post, desc => "HTTP method."}},
{headers, fun headers_no_content_type/1} {headers, fun headers_no_content_type/1}
] ++ common_fields(); ] ++ common_fields();
fields(post) -> fields(post) ->
[ [
{method, #{type => post, default => post, desc => "HTTP method."}}, {method, #{type => post, required => true, default => post, desc => "HTTP method."}},
{headers, fun headers/1} {headers, fun headers/1}
] ++ common_fields(). ] ++ common_fields().
@ -75,7 +75,7 @@ desc(_) ->
common_fields() -> common_fields() ->
[ [
{mechanism, emqx_authn_schema:mechanism('password_based')}, {mechanism, emqx_authn_schema:mechanism(password_based)},
{backend, emqx_authn_schema:backend(http)}, {backend, emqx_authn_schema:backend(http)},
{url, fun url/1}, {url, fun url/1},
{body, {body,

View File

@ -55,20 +55,22 @@ roots() ->
fields('hmac-based') -> fields('hmac-based') ->
[ [
{use_jwks, sc(hoconsc:enum([false]), #{desc => ""})}, {use_jwks, sc(hoconsc:enum([false]), #{required => true, desc => ""})},
{algorithm, sc(hoconsc:enum(['hmac-based']), #{desc => "Signing algorithm."})}, {algorithm,
sc(hoconsc:enum(['hmac-based']), #{required => true, desc => "Signing algorithm."})},
{secret, fun secret/1}, {secret, fun secret/1},
{secret_base64_encoded, fun secret_base64_encoded/1} {secret_base64_encoded, fun secret_base64_encoded/1}
] ++ common_fields(); ] ++ common_fields();
fields('public-key') -> fields('public-key') ->
[ [
{use_jwks, sc(hoconsc:enum([false]), #{desc => ""})}, {use_jwks, sc(hoconsc:enum([false]), #{required => true, desc => ""})},
{algorithm, sc(hoconsc:enum(['public-key']), #{desc => "Signing algorithm."})}, {algorithm,
sc(hoconsc:enum(['public-key']), #{required => true, desc => "Signing algorithm."})},
{certificate, fun certificate/1} {certificate, fun certificate/1}
] ++ common_fields(); ] ++ common_fields();
fields('jwks') -> fields('jwks') ->
[ [
{use_jwks, sc(hoconsc:enum([true]), #{desc => ""})}, {use_jwks, sc(hoconsc:enum([true]), #{required => true, desc => ""})},
{endpoint, fun endpoint/1}, {endpoint, fun endpoint/1},
{pool_size, fun pool_size/1}, {pool_size, fun pool_size/1},
{refresh_interval, fun refresh_interval/1}, {refresh_interval, fun refresh_interval/1},
@ -78,7 +80,8 @@ fields('jwks') ->
hoconsc:ref(?MODULE, ssl_disable) hoconsc:ref(?MODULE, ssl_disable)
]), ]),
desc => "Enable/disable SSL.", desc => "Enable/disable SSL.",
default => #{<<"enable">> => false} default => #{<<"enable">> => false},
required => false
}} }}
] ++ common_fields(); ] ++ common_fields();
fields(ssl_enable) -> fields(ssl_enable) ->
@ -114,6 +117,7 @@ common_fields() ->
secret(type) -> binary(); secret(type) -> binary();
secret(desc) -> "The key to verify the JWT Token using HMAC algorithm."; secret(desc) -> "The key to verify the JWT Token using HMAC algorithm.";
secret(required) -> true;
secret(_) -> undefined. secret(_) -> undefined.
secret_base64_encoded(type) -> boolean(); secret_base64_encoded(type) -> boolean();
@ -123,10 +127,12 @@ secret_base64_encoded(_) -> undefined.
certificate(type) -> string(); certificate(type) -> string();
certificate(desc) -> "The certificate used for signing the token."; certificate(desc) -> "The certificate used for signing the token.";
certificate(required) -> ture;
certificate(_) -> undefined. certificate(_) -> undefined.
endpoint(type) -> string(); endpoint(type) -> string();
endpoint(desc) -> "JWKs endpoint."; endpoint(desc) -> "JWKs endpoint.";
endpoint(required) -> true;
endpoint(_) -> undefined. endpoint(_) -> undefined.
refresh_interval(type) -> integer(); refresh_interval(type) -> integer();
@ -168,6 +174,8 @@ verify_claims(converter) ->
fun(VerifyClaims) -> fun(VerifyClaims) ->
[{to_binary(K), V} || {K, V} <- maps:to_list(VerifyClaims)] [{to_binary(K), V} || {K, V} <- maps:to_list(VerifyClaims)]
end; end;
verify_claims(required) ->
false;
verify_claims(_) -> verify_claims(_) ->
undefined. undefined.

View File

@ -103,8 +103,8 @@ roots() -> [?CONF_NS].
fields(?CONF_NS) -> fields(?CONF_NS) ->
[ [
{mechanism, emqx_authn_schema:mechanism('password_based')}, {mechanism, emqx_authn_schema:mechanism(password_based)},
{backend, emqx_authn_schema:backend('built_in_database')}, {backend, emqx_authn_schema:backend(built_in_database)},
{user_id_type, fun user_id_type/1}, {user_id_type, fun user_id_type/1},
{password_hash_algorithm, fun emqx_authn_password_hashing:type_rw/1} {password_hash_algorithm, fun emqx_authn_password_hashing:type_rw/1}
] ++ emqx_authn_schema:common_fields(). ] ++ emqx_authn_schema:common_fields().
@ -117,6 +117,7 @@ desc(_) ->
user_id_type(type) -> user_id_type(); user_id_type(type) -> user_id_type();
user_id_type(desc) -> "Authenticate by client ID or username."; user_id_type(desc) -> "Authenticate by client ID or username.";
user_id_type(default) -> <<"username">>; user_id_type(default) -> <<"username">>;
user_id_type(required) -> true;
user_id_type(_) -> undefined. user_id_type(_) -> undefined.
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------

View File

@ -83,6 +83,7 @@ common_fields() ->
collection(type) -> binary(); collection(type) -> binary();
collection(desc) -> "Collection used to store authentication data."; collection(desc) -> "Collection used to store authentication data.";
collection(required) -> true;
collection(_) -> undefined. collection(_) -> undefined.
selector(type) -> selector(type) ->
@ -97,6 +98,7 @@ selector(_) ->
password_hash_field(type) -> binary(); password_hash_field(type) -> binary();
password_hash_field(desc) -> "Document field that contains password hash."; password_hash_field(desc) -> "Document field that contains password hash.";
password_hash_field(required) -> false;
password_hash_field(_) -> undefined. password_hash_field(_) -> undefined.
salt_field(type) -> binary(); salt_field(type) -> binary();

View File

@ -48,7 +48,7 @@ roots() -> [?CONF_NS].
fields(?CONF_NS) -> fields(?CONF_NS) ->
[ [
{mechanism, emqx_authn_schema:mechanism('password_based')}, {mechanism, emqx_authn_schema:mechanism(password_based)},
{backend, emqx_authn_schema:backend(mysql)}, {backend, emqx_authn_schema:backend(mysql)},
{password_hash_algorithm, fun emqx_authn_password_hashing:type_ro/1}, {password_hash_algorithm, fun emqx_authn_password_hashing:type_ro/1},
{query, fun query/1}, {query, fun query/1},
@ -63,6 +63,7 @@ desc(_) ->
query(type) -> string(); query(type) -> string();
query(desc) -> "SQL query used to lookup client data."; query(desc) -> "SQL query used to lookup client data.";
query(required) -> true;
query(_) -> undefined. query(_) -> undefined.
query_timeout(type) -> emqx_schema:duration_ms(); query_timeout(type) -> emqx_schema:duration_ms();

View File

@ -54,7 +54,7 @@ roots() -> [?CONF_NS].
fields(?CONF_NS) -> fields(?CONF_NS) ->
[ [
{mechanism, emqx_authn_schema:mechanism('password_based')}, {mechanism, emqx_authn_schema:mechanism(password_based)},
{backend, emqx_authn_schema:backend(postgresql)}, {backend, emqx_authn_schema:backend(postgresql)},
{password_hash_algorithm, fun emqx_authn_password_hashing:type_ro/1}, {password_hash_algorithm, fun emqx_authn_password_hashing:type_ro/1},
{query, fun query/1} {query, fun query/1}
@ -69,6 +69,7 @@ desc(_) ->
query(type) -> string(); query(type) -> string();
query(desc) -> "`SQL` query for looking up authentication data."; query(desc) -> "`SQL` query for looking up authentication data.";
query(required) -> true;
query(_) -> undefined. query(_) -> undefined.
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------

View File

@ -79,6 +79,7 @@ common_fields() ->
cmd(type) -> string(); cmd(type) -> string();
cmd(desc) -> "Redis query."; cmd(desc) -> "Redis query.";
cmd(required) -> true;
cmd(_) -> undefined. cmd(_) -> undefined.
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------

View File

@ -56,6 +56,7 @@ roots() ->
fields(single) -> fields(single) ->
[ {mongo_type, #{type => single, [ {mongo_type, #{type => single,
default => single, default => single,
required => true,
desc => ?DESC("single_mongo_type")}} desc => ?DESC("single_mongo_type")}}
, {server, fun server/1} , {server, fun server/1}
, {w_mode, fun w_mode/1} , {w_mode, fun w_mode/1}
@ -63,6 +64,7 @@ fields(single) ->
fields(rs) -> fields(rs) ->
[ {mongo_type, #{type => rs, [ {mongo_type, #{type => rs,
default => rs, default => rs,
required => true,
desc => ?DESC("rs_mongo_type")}} desc => ?DESC("rs_mongo_type")}}
, {servers, fun servers/1} , {servers, fun servers/1}
, {w_mode, fun w_mode/1} , {w_mode, fun w_mode/1}
@ -72,6 +74,7 @@ fields(rs) ->
fields(sharded) -> fields(sharded) ->
[ {mongo_type, #{type => sharded, [ {mongo_type, #{type => sharded,
default => sharded, default => sharded,
required => true,
desc => ?DESC("sharded_mongo_type")}} desc => ?DESC("sharded_mongo_type")}}
, {servers, fun servers/1} , {servers, fun servers/1}
, {w_mode, fun w_mode/1} , {w_mode, fun w_mode/1}
@ -336,7 +339,7 @@ max_overflow(_) -> undefined.
replica_set_name(type) -> binary(); replica_set_name(type) -> binary();
replica_set_name(desc) -> ?DESC("replica_set_name"); replica_set_name(desc) -> ?DESC("replica_set_name");
replica_set_name(required) -> false; replica_set_name(required) -> true;
replica_set_name(_) -> undefined. replica_set_name(_) -> undefined.
srv_record(type) -> boolean(); srv_record(type) -> boolean();

View File

@ -57,6 +57,7 @@ fields(single) ->
[ {server, fun server/1} [ {server, fun server/1}
, {redis_type, #{type => hoconsc:enum([single]), , {redis_type, #{type => hoconsc:enum([single]),
default => single, default => single,
required => true,
desc => ?DESC("single") desc => ?DESC("single")
}} }}
] ++ ] ++
@ -66,6 +67,7 @@ fields(cluster) ->
[ {servers, fun servers/1} [ {servers, fun servers/1}
, {redis_type, #{type => hoconsc:enum([cluster]), , {redis_type, #{type => hoconsc:enum([cluster]),
default => cluster, default => cluster,
required => true,
desc => ?DESC("cluster") desc => ?DESC("cluster")
}} }}
] ++ ] ++
@ -75,6 +77,7 @@ fields(sentinel) ->
[ {servers, fun servers/1} [ {servers, fun servers/1}
, {redis_type, #{type => hoconsc:enum([sentinel]), , {redis_type, #{type => hoconsc:enum([sentinel]),
default => sentinel, default => sentinel,
required => true,
desc => ?DESC("sentinel") desc => ?DESC("sentinel")
}} }}
, {sentinel, #{type => string(), desc => ?DESC("sentinel_desc") , {sentinel, #{type => string(), desc => ?DESC("sentinel_desc")
@ -210,6 +213,7 @@ redis_fields() ->
, {password, fun emqx_connector_schema_lib:password/1} , {password, fun emqx_connector_schema_lib:password/1}
, {database, #{type => integer(), , {database, #{type => integer(),
default => 0, default => 0,
required => true,
desc => ?DESC("database") desc => ?DESC("database")
}} }}
, {auto_reconnect, fun emqx_connector_schema_lib:auto_reconnect/1} , {auto_reconnect, fun emqx_connector_schema_lib:auto_reconnect/1}