Просмотр исходного кода

fix(authn): api required fields

JimMoen 3 лет назад
Родитель
Сommit
88c98bb310

+ 7 - 7
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) ->

+ 14 - 14
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) ->

+ 18 - 14
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) ->

+ 3 - 3
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,

+ 14 - 6
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.
 

+ 3 - 2
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.
 
 %%------------------------------------------------------------------------------

+ 2 - 0
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();

+ 2 - 1
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();

+ 2 - 1
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.
 
 %%------------------------------------------------------------------------------

+ 1 - 0
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.
 
 %%------------------------------------------------------------------------------

+ 4 - 1
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();

+ 4 - 0
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}