diff --git a/apps/emqx_authn/src/emqx_authn.erl b/apps/emqx_authn/src/emqx_authn.erl index 70e662cc3..79d269a55 100644 --- a/apps/emqx_authn/src/emqx_authn.erl +++ b/apps/emqx_authn/src/emqx_authn.erl @@ -29,14 +29,14 @@ providers() -> [ - {{'password_based', 'built_in_database'}, emqx_authn_mnesia}, - {{'password_based', mysql}, emqx_authn_mysql}, - {{'password_based', postgresql}, emqx_authn_pgsql}, - {{'password_based', mongodb}, emqx_authn_mongodb}, - {{'password_based', redis}, emqx_authn_redis}, - {{'password_based', 'http'}, emqx_authn_http}, + {{password_based, built_in_database}, emqx_authn_mnesia}, + {{password_based, mysql}, emqx_authn_mysql}, + {{password_based, postgresql}, emqx_authn_pgsql}, + {{password_based, mongodb}, emqx_authn_mongodb}, + {{password_based, redis}, emqx_authn_redis}, + {{password_based, http}, emqx_authn_http}, {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) -> diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl index d1d8cbc6a..8f2f2dab7 100644 --- a/apps/emqx_authn/src/emqx_authn_api.erl +++ b/apps/emqx_authn/src/emqx_authn_api.erl @@ -128,21 +128,22 @@ roots() -> fields(request_user_create) -> [ - {user_id, binary()} + {user_id, mk(binary(), #{required => true})} | fields(request_user_update) ]; fields(request_user_update) -> [ - {password, binary()}, + {password, mk(binary(), #{required => true})}, {is_superuser, mk(boolean(), #{default => false, required => false})} ]; fields(request_move) -> - [{position, binary()}]; + [{position, mk(binary(), #{required => true})}]; fields(request_import_users) -> - [{filename, binary()}]; + %% TODO: add file update + [{filename, mk(binary(), #{required => true})}]; fields(response_user) -> [ - {user_id, binary()}, + {user_id, mk(binary(), #{required => true})}, {is_superuser, mk(boolean(), #{default => false, required => false})} ]; fields(response_users) -> @@ -425,10 +426,8 @@ schema("/authentication/:id/users") -> description => <<"List users in authenticator in global authentication chain">>, parameters => [ param_auth_id(), - {page, - mk(pos_integer(), #{in => query, desc => <<"Page Index">>, required => false})}, - {limit, - mk(pos_integer(), #{in => query, desc => <<"Page Limit">>, required => false})}, + ref(emqx_dashboard_swagger, page), + ref(emqx_dashboard_swagger, limit), {like_username, mk(binary(), #{ in => query, @@ -477,10 +476,8 @@ schema("/listeners/:listener_id/authentication/:id/users") -> parameters => [ param_listener_id(), param_auth_id(), - {page, - mk(pos_integer(), #{in => query, desc => <<"Page Index">>, required => false})}, - {limit, - mk(pos_integer(), #{in => query, desc => <<"Page Limit">>, required => false})} + ref(emqx_dashboard_swagger, page), + ref(emqx_dashboard_swagger, limit) ], responses => #{ 200 => emqx_dashboard_swagger:schema_with_example( @@ -581,7 +578,8 @@ param_auth_id() -> id, mk(binary(), #{ in => path, - desc => <<"Authenticator ID">> + desc => <<"Authenticator ID">>, + required => true }) }. @@ -591,6 +589,7 @@ param_listener_id() -> mk(binary(), #{ in => path, desc => <<"Listener ID">>, + required => true, example => emqx_listeners:id_example() }) }. @@ -1177,6 +1176,7 @@ update_config(Path, ConfigRequest) -> get_raw_config_with_defaults(ConfKeyPath) -> NConfKeyPath = [atom_to_binary(Key, utf8) || Key <- ConfKeyPath], RawConfig = emqx_map_lib:deep_get(NConfKeyPath, emqx_config:get_raw([]), []), + %% TODO: check plain unexcepted ensure_list(fill_defaults(RawConfig)). find_config(AuthenticatorID, AuthenticatorsConfig) -> diff --git a/apps/emqx_authn/src/emqx_authn_password_hashing.erl b/apps/emqx_authn/src/emqx_authn_password_hashing.erl index 959d9030a..6824f69d9 100644 --- a/apps/emqx_authn/src/emqx_authn_password_hashing.erl +++ b/apps/emqx_authn/src/emqx_authn_password_hashing.erl @@ -68,21 +68,31 @@ roots() -> [pbkdf2, bcrypt, bcrypt_rw, other_algorithms]. fields(bcrypt_rw) -> 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) -> - [{name, sc(bcrypt, #{desc => "BCRYPT password hashing."})}]; + [{name, sc(bcrypt, #{required => true, desc => "BCRYPT password hashing."})}]; fields(pbkdf2) -> [ - {name, sc(pbkdf2, #{desc => "PBKDF2 password hashing."})}, + {name, sc(pbkdf2, #{required => true, desc => "PBKDF2 password hashing."})}, {mac_fun, sc( 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, sc( integer(), - #{desc => "Iteration count for PBKDF2 hashing algorithm."} + #{required => true, desc => "Iteration count for PBKDF2 hashing algorithm."} )}, {dk_length, fun dk_length/1} ]; @@ -91,10 +101,7 @@ fields(other_algorithms) -> {name, sc( hoconsc:enum([plain, md5, sha, sha256, sha512]), - #{ - desc => - "Simple password hashing algorithm." - } + #{required => true, desc => "Simple password hashing algorithm."} )}, {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(_) -> undefined. -salt_rounds(type) -> integer(); -salt_rounds(default) -> 10; -salt_rounds(desc) -> "Salt rounds for BCRYPT password generation."; -salt_rounds(_) -> undefined. - dk_length(type) -> integer(); dk_length(required) -> @@ -130,6 +132,7 @@ dk_length(desc) -> dk_length(_) -> undefined. +%% for simple_authn/emqx_authn_mnesia type_rw(type) -> hoconsc:union(rw_refs()); type_rw(default) -> @@ -139,6 +142,7 @@ type_rw(desc) -> type_rw(_) -> undefined. +%% for other authn resources type_ro(type) -> hoconsc:union(ro_refs()); type_ro(default) -> diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl index 3dee4c2a3..d870d2a06 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl @@ -57,12 +57,12 @@ roots() -> 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} ] ++ common_fields(); fields(post) -> [ - {method, #{type => post, default => post, desc => "HTTP method."}}, + {method, #{type => post, required => true, default => post, desc => "HTTP method."}}, {headers, fun headers/1} ] ++ common_fields(). @@ -75,7 +75,7 @@ desc(_) -> common_fields() -> [ - {mechanism, emqx_authn_schema:mechanism('password_based')}, + {mechanism, emqx_authn_schema:mechanism(password_based)}, {backend, emqx_authn_schema:backend(http)}, {url, fun url/1}, {body, diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl index 6b0924760..b296e32a6 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl @@ -55,20 +55,22 @@ roots() -> fields('hmac-based') -> [ - {use_jwks, sc(hoconsc:enum([false]), #{desc => ""})}, - {algorithm, sc(hoconsc:enum(['hmac-based']), #{desc => "Signing algorithm."})}, + {use_jwks, sc(hoconsc:enum([false]), #{required => true, desc => ""})}, + {algorithm, + sc(hoconsc:enum(['hmac-based']), #{required => true, desc => "Signing algorithm."})}, {secret, fun secret/1}, {secret_base64_encoded, fun secret_base64_encoded/1} ] ++ common_fields(); fields('public-key') -> [ - {use_jwks, sc(hoconsc:enum([false]), #{desc => ""})}, - {algorithm, sc(hoconsc:enum(['public-key']), #{desc => "Signing algorithm."})}, + {use_jwks, sc(hoconsc:enum([false]), #{required => true, desc => ""})}, + {algorithm, + sc(hoconsc:enum(['public-key']), #{required => true, desc => "Signing algorithm."})}, {certificate, fun certificate/1} ] ++ common_fields(); fields('jwks') -> [ - {use_jwks, sc(hoconsc:enum([true]), #{desc => ""})}, + {use_jwks, sc(hoconsc:enum([true]), #{required => true, desc => ""})}, {endpoint, fun endpoint/1}, {pool_size, fun pool_size/1}, {refresh_interval, fun refresh_interval/1}, @@ -78,7 +80,8 @@ fields('jwks') -> hoconsc:ref(?MODULE, ssl_disable) ]), desc => "Enable/disable SSL.", - default => #{<<"enable">> => false} + default => #{<<"enable">> => false}, + required => false }} ] ++ common_fields(); fields(ssl_enable) -> @@ -114,6 +117,7 @@ common_fields() -> secret(type) -> binary(); secret(desc) -> "The key to verify the JWT Token using HMAC algorithm."; +secret(required) -> true; secret(_) -> undefined. secret_base64_encoded(type) -> boolean(); @@ -123,10 +127,12 @@ secret_base64_encoded(_) -> undefined. certificate(type) -> string(); certificate(desc) -> "The certificate used for signing the token."; +certificate(required) -> ture; certificate(_) -> undefined. endpoint(type) -> string(); endpoint(desc) -> "JWKs endpoint."; +endpoint(required) -> true; endpoint(_) -> undefined. refresh_interval(type) -> integer(); @@ -168,6 +174,8 @@ verify_claims(converter) -> fun(VerifyClaims) -> [{to_binary(K), V} || {K, V} <- maps:to_list(VerifyClaims)] end; +verify_claims(required) -> + false; verify_claims(_) -> undefined. diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl index 9d6d1820a..7971ce049 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl @@ -103,8 +103,8 @@ roots() -> [?CONF_NS]. fields(?CONF_NS) -> [ - {mechanism, emqx_authn_schema:mechanism('password_based')}, - {backend, emqx_authn_schema:backend('built_in_database')}, + {mechanism, emqx_authn_schema:mechanism(password_based)}, + {backend, emqx_authn_schema:backend(built_in_database)}, {user_id_type, fun user_id_type/1}, {password_hash_algorithm, fun emqx_authn_password_hashing:type_rw/1} ] ++ emqx_authn_schema:common_fields(). @@ -117,6 +117,7 @@ desc(_) -> user_id_type(type) -> user_id_type(); user_id_type(desc) -> "Authenticate by client ID or username."; user_id_type(default) -> <<"username">>; +user_id_type(required) -> true; user_id_type(_) -> undefined. %%------------------------------------------------------------------------------ diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl index c177316db..f5ceaa577 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl @@ -83,6 +83,7 @@ common_fields() -> collection(type) -> binary(); collection(desc) -> "Collection used to store authentication data."; +collection(required) -> true; collection(_) -> undefined. selector(type) -> @@ -97,6 +98,7 @@ selector(_) -> password_hash_field(type) -> binary(); password_hash_field(desc) -> "Document field that contains password hash."; +password_hash_field(required) -> false; password_hash_field(_) -> undefined. salt_field(type) -> binary(); diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl index 11e670f4f..4152bd888 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl @@ -48,7 +48,7 @@ roots() -> [?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)}, {password_hash_algorithm, fun emqx_authn_password_hashing:type_ro/1}, {query, fun query/1}, @@ -63,6 +63,7 @@ desc(_) -> query(type) -> string(); query(desc) -> "SQL query used to lookup client data."; +query(required) -> true; query(_) -> undefined. query_timeout(type) -> emqx_schema:duration_ms(); diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl index 34239cb87..3a9f390dd 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl @@ -54,7 +54,7 @@ roots() -> [?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)}, {password_hash_algorithm, fun emqx_authn_password_hashing:type_ro/1}, {query, fun query/1} @@ -69,6 +69,7 @@ desc(_) -> query(type) -> string(); query(desc) -> "`SQL` query for looking up authentication data."; +query(required) -> true; query(_) -> undefined. %%------------------------------------------------------------------------------ diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl index 1d37db10a..b29f0acdf 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl @@ -79,6 +79,7 @@ common_fields() -> cmd(type) -> string(); cmd(desc) -> "Redis query."; +cmd(required) -> true; cmd(_) -> undefined. %%------------------------------------------------------------------------------ diff --git a/apps/emqx_connector/src/emqx_connector_mongo.erl b/apps/emqx_connector/src/emqx_connector_mongo.erl index ca5143d44..51da5d68e 100644 --- a/apps/emqx_connector/src/emqx_connector_mongo.erl +++ b/apps/emqx_connector/src/emqx_connector_mongo.erl @@ -56,6 +56,7 @@ roots() -> fields(single) -> [ {mongo_type, #{type => single, default => single, + required => true, desc => ?DESC("single_mongo_type")}} , {server, fun server/1} , {w_mode, fun w_mode/1} @@ -63,6 +64,7 @@ fields(single) -> fields(rs) -> [ {mongo_type, #{type => rs, default => rs, + required => true, desc => ?DESC("rs_mongo_type")}} , {servers, fun servers/1} , {w_mode, fun w_mode/1} @@ -72,6 +74,7 @@ fields(rs) -> fields(sharded) -> [ {mongo_type, #{type => sharded, default => sharded, + required => true, desc => ?DESC("sharded_mongo_type")}} , {servers, fun servers/1} , {w_mode, fun w_mode/1} @@ -336,7 +339,7 @@ max_overflow(_) -> undefined. replica_set_name(type) -> binary(); replica_set_name(desc) -> ?DESC("replica_set_name"); -replica_set_name(required) -> false; +replica_set_name(required) -> true; replica_set_name(_) -> undefined. srv_record(type) -> boolean(); diff --git a/apps/emqx_connector/src/emqx_connector_redis.erl b/apps/emqx_connector/src/emqx_connector_redis.erl index 77180391c..2fb7afad0 100644 --- a/apps/emqx_connector/src/emqx_connector_redis.erl +++ b/apps/emqx_connector/src/emqx_connector_redis.erl @@ -57,6 +57,7 @@ fields(single) -> [ {server, fun server/1} , {redis_type, #{type => hoconsc:enum([single]), default => single, + required => true, desc => ?DESC("single") }} ] ++ @@ -66,6 +67,7 @@ fields(cluster) -> [ {servers, fun servers/1} , {redis_type, #{type => hoconsc:enum([cluster]), default => cluster, + required => true, desc => ?DESC("cluster") }} ] ++ @@ -75,6 +77,7 @@ fields(sentinel) -> [ {servers, fun servers/1} , {redis_type, #{type => hoconsc:enum([sentinel]), default => sentinel, + required => true, desc => ?DESC("sentinel") }} , {sentinel, #{type => string(), desc => ?DESC("sentinel_desc") @@ -210,6 +213,7 @@ redis_fields() -> , {password, fun emqx_connector_schema_lib:password/1} , {database, #{type => integer(), default => 0, + required => true, desc => ?DESC("database") }} , {auto_reconnect, fun emqx_connector_schema_lib:auto_reconnect/1}