From 5c9dabc06411eb0378ceb129585942bf1efd49c8 Mon Sep 17 00:00:00 2001 From: zhouzb Date: Fri, 30 Jul 2021 11:47:48 +0800 Subject: [PATCH 1/2] feat(authn mongo api): add api spec for mongo authn --- apps/emqx_authn/src/emqx_authn_api.erl | 126 +++++++++++++++++- .../src/emqx_connector_mongo.erl | 4 +- 2 files changed, 127 insertions(+), 3 deletions(-) diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl index f6817c900..24fafc785 100644 --- a/apps/emqx_authn/src/emqx_authn_api.erl +++ b/apps/emqx_authn/src/emqx_authn_api.erl @@ -61,6 +61,21 @@ <<"username">> => <<"${mqtt-username}">> }}). +-define(EXAMPLE_4, #{name => <<"example 4">>, + mechanism => <<"password-based">>, + server_type => <<"mongodb">>, + server => <<"127.0.0.1:27017">>, + database => example, + collection => users, + selector => #{ + username => <<"${mqtt-username}">> + }, + password_hash_field => <<"password_hash">>, + salt_field => <<"salt">>, + password_hash_algorithm => <<"sha256">>, + salt_position => <<"prefix">> + }). + -define(ERR_RESPONSE(Desc), #{description => Desc, content => #{ 'application/json' => #{ @@ -109,6 +124,12 @@ authentication_api() -> } } } + }, + responses => #{ + <<"204">> => #{ + description => <<"No Content">> + }, + <<"400">> => ?ERR_RESPONSE(<<"Bad Request">>) } } }, @@ -134,6 +155,10 @@ authenticators_api() -> jwt => #{ summary => <<"JWT Authentication">>, value => emqx_json:encode(?EXAMPLE_3) + }, + mongodb => #{ + summary => <<"Authentication with MongoDB">>, + value => emqx_json:encode(?EXAMPLE_4) } } } @@ -157,6 +182,10 @@ authenticators_api() -> example3 => #{ summary => <<"Example 3">>, value => emqx_json:encode(maps:put(id, <<"example 3">>, ?EXAMPLE_3)) + }, + example4 => #{ + summary => <<"Example 4">>, + value => emqx_json:encode(maps:put(id, <<"example 4">>, ?EXAMPLE_4)) } } } @@ -183,6 +212,7 @@ authenticators_api() -> value => emqx_json:encode([ maps:put(id, <<"example 1">>, ?EXAMPLE_1) , maps:put(id, <<"example 2">>, ?EXAMPLE_2) , maps:put(id, <<"example 3">>, ?EXAMPLE_3) + , maps:put(id, <<"example 4">>, ?EXAMPLE_4) ]) } } @@ -226,6 +256,10 @@ authenticators_api2() -> example3 => #{ summary => <<"Example 3">>, value => emqx_json:encode(maps:put(id, <<"example 3">>, ?EXAMPLE_3)) + }, + example4 => #{ + summary => <<"Example 4">>, + value => emqx_json:encode(maps:put(id, <<"example 4">>, ?EXAMPLE_4)) } } } @@ -286,6 +320,10 @@ authenticators_api2() -> example3 => #{ summary => <<"Example 3">>, value => emqx_json:encode(maps:put(id, <<"example 3">>, ?EXAMPLE_3)) + }, + example4 => #{ + summary => <<"Example 4">>, + value => emqx_json:encode(maps:put(id, <<"example 4">>, ?EXAMPLE_4)) } } } @@ -624,7 +662,6 @@ users2_api() -> }, {"/authentication/authenticators/:id/users/:user_id", Metadata, users2}. - definitions() -> AuthenticatorDef = #{ oneOf => [ minirest:ref(<<"password_based">>) @@ -673,6 +710,7 @@ definitions() -> oneOf => [ minirest:ref(<<"password_based_built_in_database">>) , minirest:ref(<<"password_based_mysql">>) , minirest:ref(<<"password_based_pgsql">>) + , minirest:ref(<<"password_based_mongodb">>) , minirest:ref(<<"password_based_http_server">>) ] } @@ -869,6 +907,91 @@ definitions() -> } }, + PasswordBasedMongoDBDef = #{ + type => object, + required => [ server_type + , server + , servers + , replica_set_name + , database + , username + , password + , collection + , selector + , password_hash_field + ], + properties => #{ + server_type => #{ + type => string, + enum => [<<"mongodb">>], + example => [<<"mongodb">>] + }, + server => #{ + description => <<"Mutually exclusive with the 'servers' field, only valid in standalone mode">>, + type => string, + example => <<"127.0.0.1:27017">> + }, + servers => #{ + description => <<"Mutually exclusive with the 'server' field, only valid in replica set and sharded mode">>, + type => array, + items => #{ + type => string + }, + example => [<<"127.0.0.1:27017">>] + }, + replica_set_name => #{ + description => <<"Only valid in replica set mode">>, + type => string + }, + database => #{ + type => string + }, + username => #{ + type => string + }, + password => #{ + type => string + }, + auth_source => #{ + type => string, + default => <<"admin">> + }, + pool_size => #{ + type => integer, + default => 8 + }, + collection => #{ + type => string + }, + selector => #{ + type => object, + additionalProperties => true, + example => <<"{\"username\":\"${mqtt-username}\"}">> + }, + password_hash_field => #{ + type => string, + example => <<"password_hash">> + }, + salt_field => #{ + type => string, + example => <<"salt">> + }, + password_hash_algorithm => #{ + type => string, + enum => [<<"plain">>, <<"md5">>, <<"sha">>, <<"sha256">>, <<"sha512">>, <<"bcrypt">>], + default => <<"sha256">>, + example => <<"sha256">> + }, + salt_position => #{ + description => <<"Only valid when the 'salt_field' field is specified">>, + type => string, + enum => [<<"prefix">>, <<"suffix">>], + default => <<"prefix">>, + example => <<"prefix">> + } + } + }, + PasswordBasedHTTPServerDef = #{ type => object, properties => #{ @@ -995,6 +1118,7 @@ definitions() -> , #{<<"password_based_built_in_database">> => PasswordBasedBuiltInDatabaseDef} , #{<<"password_based_mysql">> => PasswordBasedMySQLDef} , #{<<"password_based_pgsql">> => PasswordBasedPgSQLDef} + , #{<<"password_based_mongodb">> => PasswordBasedMongoDBDef} , #{<<"password_based_http_server">> => PasswordBasedHTTPServerDef} , #{<<"password_hash_algorithm">> => PasswordHashAlgorithmDef} , #{<<"ssl">> => SSLDef} diff --git a/apps/emqx_connector/src/emqx_connector_mongo.erl b/apps/emqx_connector/src/emqx_connector_mongo.erl index f21fb4bf4..4af339538 100644 --- a/apps/emqx_connector/src/emqx_connector_mongo.erl +++ b/apps/emqx_connector/src/emqx_connector_mongo.erl @@ -54,7 +54,7 @@ fields(rs) -> [ {mongo_type, #{type => rs, default => rs}} , {servers, fun servers/1} - , {replicaset_name, fun emqx_connector_schema_lib:database/1} + , {replica_set_name, fun emqx_connector_schema_lib:database/1} ] ++ mongo_fields(); fields(sharded) -> [ {mongo_type, #{type => sharded, @@ -98,7 +98,7 @@ on_start(InstId, Config = #{server := Server, on_start(InstId, Config = #{servers := Servers, mongo_type := rs, - replicaset_name := RsName}) -> + replica_set_name := RsName}) -> logger:info("starting mongodb connector: ~p, config: ~p", [InstId, Config]), Opts = [{type, {rs, RsName}}, {hosts, Servers}], From 1c3d46d29e66d508cf9a9c5a14edf476b46b8a65 Mon Sep 17 00:00:00 2001 From: zhouzb Date: Fri, 30 Jul 2021 12:01:17 +0800 Subject: [PATCH 2/2] feat(authn api): add required spec --- apps/emqx_authn/src/emqx_authn_api.erl | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl index 24fafc785..c0071114a 100644 --- a/apps/emqx_authn/src/emqx_authn_api.erl +++ b/apps/emqx_authn/src/emqx_authn_api.erl @@ -574,7 +574,6 @@ users2_api() -> type => array, items => #{ type => object, - required => [user_id], properties => #{ user_id => #{ type => string @@ -618,7 +617,6 @@ users2_api() -> type => array, items => #{ type => object, - required => [user_id], properties => #{ user_id => #{ type => string @@ -763,7 +761,7 @@ definitions() -> SCRAMDef = #{ type => object, - required => [name, mechanism], + required => [name, mechanism, server_type], properties => #{ name => #{ type => string, @@ -793,6 +791,7 @@ definitions() -> PasswordBasedBuiltInDatabaseDef = #{ type => object, + required => [server_type], properties => #{ server_type => #{ type => string, @@ -811,6 +810,12 @@ definitions() -> PasswordBasedMySQLDef = #{ type => object, + required => [ server_type + , server + , database + , username + , password + , query], properties => #{ server_type => #{ type => string, @@ -863,6 +868,12 @@ definitions() -> PasswordBasedPgSQLDef = #{ type => object, + required => [ server_type + , server + , database + , username + , password + , query], properties => #{ server_type => #{ type => string, @@ -994,6 +1005,10 @@ definitions() -> PasswordBasedHTTPServerDef = #{ type => object, + required => [ server_type + , url + , form_data + ], properties => #{ server_type => #{ type => string, @@ -1015,7 +1030,7 @@ definitions() -> type => string } }, - format_data => #{ + form_data => #{ type => string }, connect_timeout => #{ @@ -1054,7 +1069,7 @@ definitions() -> enum => [<<"plain">>, <<"md5">>, <<"sha">>, <<"sha256">>, <<"sha512">>, <<"bcrypt">>], default => <<"sha256">> }, - salt_rounds => #{ + salt_rounds => #{ type => integer, default => 10 }