diff --git a/apps/emqx/include/http_api.hrl b/apps/emqx/include/http_api.hrl index 0f6372584..f0c5611e9 100644 --- a/apps/emqx/include/http_api.hrl +++ b/apps/emqx/include/http_api.hrl @@ -17,6 +17,7 @@ %% HTTP API Auth -define(BAD_USERNAME_OR_PWD, 'BAD_USERNAME_OR_PWD'). -define(BAD_API_KEY_OR_SECRET, 'BAD_API_KEY_OR_SECRET'). +-define(API_KEY_NOT_ALLOW, 'API_KEY_NOT_ALLOW'). -define(API_KEY_NOT_ALLOW_MSG, <<"This API Key don't have permission to access this resource">>). %% Bad Request diff --git a/apps/emqx_dashboard/src/emqx_dashboard.erl b/apps/emqx_dashboard/src/emqx_dashboard.erl index 96f81ca84..a4438f6c7 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard.erl @@ -264,10 +264,11 @@ api_key_authorize(Req, Key, Secret) -> case emqx_mgmt_auth:authorize(Path, Req, Key, Secret) of ok -> {ok, #{auth_type => api_key, source => Key}}; - {error, <<"not_allowed">>} -> + {error, <<"not_allowed">>, Resource} -> return_unauthorized( - ?BAD_API_KEY_OR_SECRET, - <<"Not allowed, Check api_key/api_secret">> + ?API_KEY_NOT_ALLOW, + <<"Please use bearer Token instead, using API key/secret in ", Resource/binary, + " path is not permitted">> ); {error, unauthorized_role} -> {403, 'UNAUTHORIZED_ROLE', ?API_KEY_NOT_ALLOW_MSG}; diff --git a/apps/emqx_dashboard/src/emqx_dashboard_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_api.erl index 8a81f2116..d7ed5941f 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_api.erl @@ -89,6 +89,7 @@ schema("/logout") -> post => #{ tags => [<<"dashboard">>], desc => ?DESC(logout_api), + security => [#{'bearerAuth' => []}], parameters => sso_parameters(), 'requestBody' => fields([username]), responses => #{ diff --git a/apps/emqx_management/src/emqx_mgmt_api_api_keys.erl b/apps/emqx_management/src/emqx_mgmt_api_api_keys.erl index db20e9477..ad4b53401 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_api_keys.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_api_keys.erl @@ -40,6 +40,7 @@ schema("/api_key") -> get => #{ description => ?DESC(api_key_list), tags => ?TAGS, + security => [#{'bearerAuth' => []}], responses => #{ 200 => delete([api_secret], fields(app)) } @@ -47,6 +48,7 @@ schema("/api_key") -> post => #{ description => ?DESC(create_new_api_key), tags => ?TAGS, + security => [#{'bearerAuth' => []}], 'requestBody' => delete([created_at, api_key, api_secret], fields(app)), responses => #{ 200 => hoconsc:ref(app), diff --git a/apps/emqx_management/src/emqx_mgmt_auth.erl b/apps/emqx_management/src/emqx_mgmt_auth.erl index 559344e2b..7745207ce 100644 --- a/apps/emqx_management/src/emqx_mgmt_auth.erl +++ b/apps/emqx_management/src/emqx_mgmt_auth.erl @@ -184,11 +184,11 @@ list() -> to_map(ets:match_object(?APP, #?APP{_ = '_'})). authorize(<<"/api/v5/users", _/binary>>, _Req, _ApiKey, _ApiSecret) -> - {error, <<"not_allowed">>}; + {error, <<"not_allowed">>, <<"users">>}; authorize(<<"/api/v5/api_key", _/binary>>, _Req, _ApiKey, _ApiSecret) -> - {error, <<"not_allowed">>}; + {error, <<"not_allowed">>, <<"api_key">>}; authorize(<<"/api/v5/logout", _/binary>>, _Req, _ApiKey, _ApiSecret) -> - {error, <<"not_allowed">>}; + {error, <<"not_allowed">>, <<"logout">>}; authorize(_Path, Req, ApiKey, ApiSecret) -> Now = erlang:system_time(second), case find_by_api_key(ApiKey) of diff --git a/apps/emqx_management/test/emqx_mgmt_api_api_keys_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_api_api_keys_SUITE.erl index d437e07c9..760ab1732 100644 --- a/apps/emqx_management/test/emqx_mgmt_api_api_keys_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_api_api_keys_SUITE.erl @@ -394,8 +394,23 @@ t_authorize(_Config) -> {ok, _Status} = emqx_mgmt_api_test_util:request_api(get, BanPath, BasicHeader), ?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, BanPath, KeyError)), ?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, BanPath, SecretError)), - ?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, ApiKeyPath, BasicHeader)), ?assertEqual(Unauthorized, emqx_mgmt_api_test_util:request_api(get, UserPath, BasicHeader)), + {error, {{"HTTP/1.1", 401, "Unauthorized"}, _Headers, Body}} = + emqx_mgmt_api_test_util:request_api( + get, + ApiKeyPath, + [], + BasicHeader, + [], + #{return_all => true} + ), + ?assertMatch( + #{ + <<"code">> := <<"API_KEY_NOT_ALLOW">>, + <<"message">> := _ + }, + emqx_utils_json:decode(Body, [return_maps]) + ), ?assertMatch( {ok, #{<<"api_key">> := _, <<"enable">> := false}}, diff --git a/rel/i18n/emqx_mgmt_api_api_keys.hocon b/rel/i18n/emqx_mgmt_api_api_keys.hocon index 8acbe60d0..4becd01aa 100644 --- a/rel/i18n/emqx_mgmt_api_api_keys.hocon +++ b/rel/i18n/emqx_mgmt_api_api_keys.hocon @@ -1,27 +1,27 @@ emqx_mgmt_api_api_keys { api_key_list.desc: -"""Return api_key list""" +"""Return api_key list. This API can only be requested using a bearer token.""" api_key_list.label: """Return api_key list""" create_new_api_key.desc: -"""Create new api_key""" +"""Create new api_key. This API can only be requested using a bearer token.""" create_new_api_key.label: """Create new api_key""" get_api_key.desc: -"""Return the specific api_key""" +"""Return the specific api_key. This API can only be requested using a bearer token.""" get_api_key.label: """Return the specific api_key""" update_api_key.desc: -"""Update the specific api_key""" +"""Update the specific api_key. This API can only be requested using a bearer token.""" update_api_key.label: """Update the specific api_key""" delete_api_key.desc: -"""Delete the specific api_key""" +"""Delete the specific api_key. This API can only be requested using a bearer token.""" delete_api_key.label: """Delete the specific api_key"""